summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorMatthew Vogt <matthew.vogt@nokia.com>2012-01-30 14:16:15 +1000
committerMatthew Vogt <matthew.vogt@nokia.com>2012-01-30 14:16:15 +1000
commit12a5ddf456ba8549645a8cb28a8b4ed6197a14da (patch)
tree63ee2c88af936e0609a3a194f5bcc304c4c0b707 /src/declarative
Import relevant source from Qt 4.8
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/QmlChanges.txt364
-rw-r--r--src/declarative/debugger/debugger.pri33
-rw-r--r--src/declarative/debugger/qdeclarativedebug.h67
-rw-r--r--src/declarative/debugger/qdeclarativedebugclient.cpp292
-rw-r--r--src/declarative/debugger/qdeclarativedebugclient_p.h103
-rw-r--r--src/declarative/debugger/qdeclarativedebuggerstatus.cpp54
-rw-r--r--src/declarative/debugger/qdeclarativedebuggerstatus_p.h68
-rw-r--r--src/declarative/debugger/qdeclarativedebughelper.cpp76
-rw-r--r--src/declarative/debugger/qdeclarativedebughelper_p.h73
-rw-r--r--src/declarative/debugger/qdeclarativedebugserver.cpp426
-rw-r--r--src/declarative/debugger/qdeclarativedebugserver_p.h91
-rw-r--r--src/declarative/debugger/qdeclarativedebugserverconnection_p.h74
-rw-r--r--src/declarative/debugger/qdeclarativedebugservice.cpp230
-rw-r--r--src/declarative/debugger/qdeclarativedebugservice_p.h96
-rw-r--r--src/declarative/debugger/qdeclarativedebugservice_p_p.h71
-rw-r--r--src/declarative/debugger/qdeclarativedebugtrace.cpp225
-rw-r--r--src/declarative/debugger/qdeclarativedebugtrace_p.h132
-rw-r--r--src/declarative/debugger/qdeclarativeenginedebug.cpp1068
-rw-r--r--src/declarative/debugger/qdeclarativeenginedebug_p.h387
-rw-r--r--src/declarative/debugger/qdeclarativeenginedebugservice.cpp747
-rw-r--r--src/declarative/debugger/qdeclarativeenginedebugservice_p.h134
-rw-r--r--src/declarative/debugger/qdeclarativeinspectorinterface_p.h69
-rw-r--r--src/declarative/debugger/qdeclarativeinspectorservice.cpp147
-rw-r--r--src/declarative/debugger/qdeclarativeinspectorservice_p.h93
-rw-r--r--src/declarative/debugger/qjsdebuggeragent.cpp614
-rw-r--r--src/declarative/debugger/qjsdebuggeragent_p.h229
-rw-r--r--src/declarative/debugger/qjsdebugservice.cpp259
-rw-r--r--src/declarative/debugger/qjsdebugservice_p.h123
-rw-r--r--src/declarative/debugger/qpacketprotocol.cpp557
-rw-r--r--src/declarative/debugger/qpacketprotocol_p.h127
-rw-r--r--src/declarative/declarative.pro43
-rw-r--r--src/declarative/graphicsitems/graphicsitems.pri94
-rw-r--r--src/declarative/graphicsitems/qdeclarativeanchors.cpp1165
-rw-r--r--src/declarative/graphicsitems/qdeclarativeanchors_p.h204
-rw-r--r--src/declarative/graphicsitems/qdeclarativeanchors_p_p.h170
-rw-r--r--src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp404
-rw-r--r--src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h116
-rw-r--r--src/declarative/graphicsitems/qdeclarativeanimatedimage_p_p.h87
-rw-r--r--src/declarative/graphicsitems/qdeclarativeborderimage.cpp623
-rw-r--r--src/declarative/graphicsitems/qdeclarativeborderimage_p.h109
-rw-r--r--src/declarative/graphicsitems/qdeclarativeborderimage_p_p.h106
-rw-r--r--src/declarative/graphicsitems/qdeclarativeevents.cpp237
-rw-r--r--src/declarative/graphicsitems/qdeclarativeevents_p_p.h141
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable.cpp1805
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable_p.h229
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable_p_p.h244
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflipable.cpp254
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflipable_p.h100
-rw-r--r--src/declarative/graphicsitems/qdeclarativefocuspanel.cpp89
-rw-r--r--src/declarative/graphicsitems/qdeclarativefocuspanel_p.h78
-rw-r--r--src/declarative/graphicsitems/qdeclarativefocusscope.cpp73
-rw-r--r--src/declarative/graphicsitems/qdeclarativefocusscope_p.h69
-rw-r--r--src/declarative/graphicsitems/qdeclarativegraphicswidget.cpp125
-rw-r--r--src/declarative/graphicsitems/qdeclarativegraphicswidget_p.h90
-rw-r--r--src/declarative/graphicsitems/qdeclarativegridview.cpp3172
-rw-r--r--src/declarative/graphicsitems/qdeclarativegridview_p.h286
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimage.cpp584
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimage_p.h100
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimage_p_p.h79
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase.cpp284
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase_p.h116
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h93
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimplicitsizeitem.cpp92
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p.h100
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p_p.h90
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem.cpp3759
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem.h234
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem_p.h624
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitemchangelistener_p.h76
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp261
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitemsmodule_p.h63
-rw-r--r--src/declarative/graphicsitems/qdeclarativelayoutitem.cpp112
-rw-r--r--src/declarative/graphicsitems/qdeclarativelayoutitem_p.h94
-rw-r--r--src/declarative/graphicsitems/qdeclarativelistview.cpp3651
-rw-r--r--src/declarative/graphicsitems/qdeclarativelistview_p.h370
-rw-r--r--src/declarative/graphicsitems/qdeclarativeloader.cpp597
-rw-r--r--src/declarative/graphicsitems/qdeclarativeloader_p.h108
-rw-r--r--src/declarative/graphicsitems/qdeclarativeloader_p_p.h91
-rw-r--r--src/declarative/graphicsitems/qdeclarativemousearea.cpp988
-rw-r--r--src/declarative/graphicsitems/qdeclarativemousearea_p.h218
-rw-r--r--src/declarative/graphicsitems/qdeclarativemousearea_p_p.h128
-rw-r--r--src/declarative/graphicsitems/qdeclarativepainteditem.cpp497
-rw-r--r--src/declarative/graphicsitems/qdeclarativepainteditem_p.h118
-rw-r--r--src/declarative/graphicsitems/qdeclarativepainteditem_p_p.h90
-rw-r--r--src/declarative/graphicsitems/qdeclarativepath.cpp922
-rw-r--r--src/declarative/graphicsitems/qdeclarativepath_p.h286
-rw-r--r--src/declarative/graphicsitems/qdeclarativepath_p_p.h82
-rw-r--r--src/declarative/graphicsitems/qdeclarativepathview.cpp1729
-rw-r--r--src/declarative/graphicsitems/qdeclarativepathview_p.h252
-rw-r--r--src/declarative/graphicsitems/qdeclarativepathview_p_p.h192
-rw-r--r--src/declarative/graphicsitems/qdeclarativepincharea.cpp607
-rw-r--r--src/declarative/graphicsitems/qdeclarativepincharea_p.h313
-rw-r--r--src/declarative/graphicsitems/qdeclarativepincharea_p_p.h115
-rw-r--r--src/declarative/graphicsitems/qdeclarativepositioners.cpp1371
-rw-r--r--src/declarative/graphicsitems/qdeclarativepositioners_p.h233
-rw-r--r--src/declarative/graphicsitems/qdeclarativepositioners_p_p.h173
-rw-r--r--src/declarative/graphicsitems/qdeclarativerectangle.cpp587
-rw-r--r--src/declarative/graphicsitems/qdeclarativerectangle_p.h188
-rw-r--r--src/declarative/graphicsitems/qdeclarativerectangle_p_p.h112
-rw-r--r--src/declarative/graphicsitems/qdeclarativerepeater.cpp447
-rw-r--r--src/declarative/graphicsitems/qdeclarativerepeater_p.h110
-rw-r--r--src/declarative/graphicsitems/qdeclarativerepeater_p_p.h82
-rw-r--r--src/declarative/graphicsitems/qdeclarativescalegrid.cpp213
-rw-r--r--src/declarative/graphicsitems/qdeclarativescalegrid_p_p.h134
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext.cpp1635
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext_p.h211
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext_p_p.h143
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextedit.cpp1895
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextedit_p.h305
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextedit_p_p.h138
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput.cpp2009
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput_p.h304
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput_p_p.h157
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextlayout.cpp391
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextlayout_p.h75
-rw-r--r--src/declarative/graphicsitems/qdeclarativetranslate.cpp125
-rw-r--r--src/declarative/graphicsitems/qdeclarativetranslate_p.h89
-rw-r--r--src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp1425
-rw-r--r--src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h257
-rw-r--r--src/declarative/qml/parser/parser.pri21
-rw-r--r--src/declarative/qml/parser/qdeclarativejs.g3149
-rw-r--r--src/declarative/qml/parser/qdeclarativejsast.cpp956
-rw-r--r--src/declarative/qml/parser/qdeclarativejsast_p.h2546
-rw-r--r--src/declarative/qml/parser/qdeclarativejsastfwd_p.h189
-rw-r--r--src/declarative/qml/parser/qdeclarativejsastvisitor.cpp58
-rw-r--r--src/declarative/qml/parser/qdeclarativejsastvisitor_p.h335
-rw-r--r--src/declarative/qml/parser/qdeclarativejsengine_p.cpp212
-rw-r--r--src/declarative/qml/parser/qdeclarativejsengine_p.h167
-rw-r--r--src/declarative/qml/parser/qdeclarativejsglobal_p.h64
-rw-r--r--src/declarative/qml/parser/qdeclarativejsgrammar.cpp989
-rw-r--r--src/declarative/qml/parser/qdeclarativejsgrammar_p.h210
-rw-r--r--src/declarative/qml/parser/qdeclarativejslexer.cpp1258
-rw-r--r--src/declarative/qml/parser/qdeclarativejslexer_p.h249
-rw-r--r--src/declarative/qml/parser/qdeclarativejsmemorypool_p.h133
-rw-r--r--src/declarative/qml/parser/qdeclarativejsnodepool_p.h139
-rw-r--r--src/declarative/qml/parser/qdeclarativejsparser.cpp1904
-rw-r--r--src/declarative/qml/parser/qdeclarativejsparser_p.h246
-rw-r--r--src/declarative/qml/qbitfield_p.h165
-rw-r--r--src/declarative/qml/qdeclarative.h415
-rw-r--r--src/declarative/qml/qdeclarativebinding.cpp573
-rw-r--r--src/declarative/qml/qdeclarativebinding_p.h193
-rw-r--r--src/declarative/qml/qdeclarativebinding_p_p.h85
-rw-r--r--src/declarative/qml/qdeclarativeboundsignal.cpp306
-rw-r--r--src/declarative/qml/qdeclarativeboundsignal_p.h103
-rw-r--r--src/declarative/qml/qdeclarativecleanup.cpp87
-rw-r--r--src/declarative/qml/qdeclarativecleanup_p.h79
-rw-r--r--src/declarative/qml/qdeclarativecompiledbindings.cpp2921
-rw-r--r--src/declarative/qml/qdeclarativecompiledbindings_p.h116
-rw-r--r--src/declarative/qml/qdeclarativecompileddata.cpp255
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp3129
-rw-r--r--src/declarative/qml/qdeclarativecompiler_p.h351
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp1086
-rw-r--r--src/declarative/qml/qdeclarativecomponent.h132
-rw-r--r--src/declarative/qml/qdeclarativecomponent_p.h161
-rw-r--r--src/declarative/qml/qdeclarativecontext.cpp774
-rw-r--r--src/declarative/qml/qdeclarativecontext.h114
-rw-r--r--src/declarative/qml/qdeclarativecontext_p.h292
-rw-r--r--src/declarative/qml/qdeclarativecontextscriptclass.cpp335
-rw-r--r--src/declarative/qml/qdeclarativecontextscriptclass_p.h106
-rw-r--r--src/declarative/qml/qdeclarativecustomparser.cpp317
-rw-r--r--src/declarative/qml/qdeclarativecustomparser_p.h167
-rw-r--r--src/declarative/qml/qdeclarativecustomparser_p_p.h89
-rw-r--r--src/declarative/qml/qdeclarativedata_p.h165
-rw-r--r--src/declarative/qml/qdeclarativedirparser.cpp285
-rw-r--r--src/declarative/qml/qdeclarativedirparser_p.h149
-rw-r--r--src/declarative/qml/qdeclarativedom.cpp1835
-rw-r--r--src/declarative/qml/qdeclarativedom_p.h362
-rw-r--r--src/declarative/qml/qdeclarativedom_p_p.h157
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp2523
-rw-r--r--src/declarative/qml/qdeclarativeengine.h130
-rw-r--r--src/declarative/qml/qdeclarativeengine_p.h387
-rw-r--r--src/declarative/qml/qdeclarativeerror.cpp285
-rw-r--r--src/declarative/qml/qdeclarativeerror.h86
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp875
-rw-r--r--src/declarative/qml/qdeclarativeexpression.h119
-rw-r--r--src/declarative/qml/qdeclarativeexpression_p.h233
-rw-r--r--src/declarative/qml/qdeclarativeextensioninterface.h68
-rw-r--r--src/declarative/qml/qdeclarativeextensionplugin.cpp171
-rw-r--r--src/declarative/qml/qdeclarativeextensionplugin.h76
-rw-r--r--src/declarative/qml/qdeclarativefastproperties.cpp101
-rw-r--r--src/declarative/qml/qdeclarativefastproperties_p.h75
-rw-r--r--src/declarative/qml/qdeclarativeglobal_p.h110
-rw-r--r--src/declarative/qml/qdeclarativeglobalscriptclass.cpp147
-rw-r--r--src/declarative/qml/qdeclarativeglobalscriptclass_p.h86
-rw-r--r--src/declarative/qml/qdeclarativeguard_p.h214
-rw-r--r--src/declarative/qml/qdeclarativeimageprovider.cpp259
-rw-r--r--src/declarative/qml/qdeclarativeimageprovider.h80
-rw-r--r--src/declarative/qml/qdeclarativeimport.cpp1083
-rw-r--r--src/declarative/qml/qdeclarativeimport_p.h144
-rw-r--r--src/declarative/qml/qdeclarativeinclude.cpp310
-rw-r--r--src/declarative/qml/qdeclarativeinclude_p.h115
-rw-r--r--src/declarative/qml/qdeclarativeinfo.cpp179
-rw-r--r--src/declarative/qml/qdeclarativeinfo.h105
-rw-r--r--src/declarative/qml/qdeclarativeinstruction.cpp230
-rw-r--r--src/declarative/qml/qdeclarativeinstruction_p.h359
-rw-r--r--src/declarative/qml/qdeclarativeintegercache.cpp96
-rw-r--r--src/declarative/qml/qdeclarativeintegercache_p.h112
-rw-r--r--src/declarative/qml/qdeclarativelist.cpp417
-rw-r--r--src/declarative/qml/qdeclarativelist.h152
-rw-r--r--src/declarative/qml/qdeclarativelist_p.h85
-rw-r--r--src/declarative/qml/qdeclarativelistscriptclass.cpp149
-rw-r--r--src/declarative/qml/qdeclarativelistscriptclass_p.h87
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp1536
-rw-r--r--src/declarative/qml/qdeclarativemetatype_p.h174
-rw-r--r--src/declarative/qml/qdeclarativenetworkaccessmanagerfactory.cpp103
-rw-r--r--src/declarative/qml/qdeclarativenetworkaccessmanagerfactory.h66
-rw-r--r--src/declarative/qml/qdeclarativenotifier.cpp126
-rw-r--r--src/declarative/qml/qdeclarativenotifier_p.h268
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass.cpp1242
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass_p.h166
-rw-r--r--src/declarative/qml/qdeclarativeparser.cpp437
-rw-r--r--src/declarative/qml/qdeclarativeparser_p.h381
-rw-r--r--src/declarative/qml/qdeclarativeparserstatus.cpp107
-rw-r--r--src/declarative/qml/qdeclarativeparserstatus.h75
-rw-r--r--src/declarative/qml/qdeclarativeprivate.h249
-rw-r--r--src/declarative/qml/qdeclarativeproperty.cpp1654
-rw-r--r--src/declarative/qml/qdeclarativeproperty.h143
-rw-r--r--src/declarative/qml/qdeclarativeproperty_p.h147
-rw-r--r--src/declarative/qml/qdeclarativepropertycache.cpp471
-rw-r--r--src/declarative/qml/qdeclarativepropertycache_p.h240
-rw-r--r--src/declarative/qml/qdeclarativepropertyvalueinterceptor.cpp79
-rw-r--r--src/declarative/qml/qdeclarativepropertyvalueinterceptor.h68
-rw-r--r--src/declarative/qml/qdeclarativepropertyvaluesource.cpp76
-rw-r--r--src/declarative/qml/qdeclarativepropertyvaluesource.h67
-rw-r--r--src/declarative/qml/qdeclarativeproxymetaobject.cpp124
-rw-r--r--src/declarative/qml/qdeclarativeproxymetaobject_p.h100
-rw-r--r--src/declarative/qml/qdeclarativerefcount.cpp70
-rw-r--r--src/declarative/qml/qdeclarativerefcount_p.h80
-rw-r--r--src/declarative/qml/qdeclarativerewrite.cpp273
-rw-r--r--src/declarative/qml/qdeclarativerewrite_p.h127
-rw-r--r--src/declarative/qml/qdeclarativescriptparser.cpp1206
-rw-r--r--src/declarative/qml/qdeclarativescriptparser_p.h148
-rw-r--r--src/declarative/qml/qdeclarativescriptstring.cpp166
-rw-r--r--src/declarative/qml/qdeclarativescriptstring.h87
-rw-r--r--src/declarative/qml/qdeclarativesqldatabase.cpp448
-rw-r--r--src/declarative/qml/qdeclarativesqldatabase_p.h67
-rw-r--r--src/declarative/qml/qdeclarativestringconverters.cpp278
-rw-r--r--src/declarative/qml/qdeclarativestringconverters_p.h91
-rw-r--r--src/declarative/qml/qdeclarativetypeloader.cpp1196
-rw-r--r--src/declarative/qml/qdeclarativetypeloader_p.h330
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache.cpp118
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache_p.h119
-rw-r--r--src/declarative/qml/qdeclarativetypenamescriptclass.cpp165
-rw-r--r--src/declarative/qml/qdeclarativetypenamescriptclass_p.h92
-rw-r--r--src/declarative/qml/qdeclarativetypenotavailable.cpp53
-rw-r--r--src/declarative/qml/qdeclarativetypenotavailable_p.h65
-rw-r--r--src/declarative/qml/qdeclarativevaluetype.cpp1011
-rw-r--r--src/declarative/qml/qdeclarativevaluetype_p.h556
-rw-r--r--src/declarative/qml/qdeclarativevaluetypescriptclass.cpp242
-rw-r--r--src/declarative/qml/qdeclarativevaluetypescriptclass_p.h87
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp1124
-rw-r--r--src/declarative/qml/qdeclarativevme_p.h95
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject.cpp903
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject_p.h197
-rw-r--r--src/declarative/qml/qdeclarativewatcher.cpp188
-rw-r--r--src/declarative/qml/qdeclarativewatcher_p.h94
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript.cpp753
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript_p.h129
-rw-r--r--src/declarative/qml/qdeclarativexmlhttprequest.cpp1740
-rw-r--r--src/declarative/qml/qdeclarativexmlhttprequest_p.h71
-rw-r--r--src/declarative/qml/qmetaobjectbuilder.cpp2601
-rw-r--r--src/declarative/qml/qmetaobjectbuilder_p.h325
-rw-r--r--src/declarative/qml/qml.pri139
-rw-r--r--src/declarative/qml/qperformancetimer.cpp227
-rw-r--r--src/declarative/qml/qperformancetimer_p.h79
-rw-r--r--src/declarative/qml/qpodvector_p.h173
-rw-r--r--src/declarative/qml/rewriter/rewriter.pri4
-rw-r--r--src/declarative/qml/rewriter/textwriter.cpp217
-rw-r--r--src/declarative/qml/rewriter/textwriter_p.h101
-rw-r--r--src/declarative/util/qdeclarativeanimation.cpp2952
-rw-r--r--src/declarative/util/qdeclarativeanimation_p.h528
-rw-r--r--src/declarative/util/qdeclarativeanimation_p_p.h397
-rw-r--r--src/declarative/util/qdeclarativeapplication.cpp112
-rw-r--r--src/declarative/util/qdeclarativeapplication_p.h86
-rw-r--r--src/declarative/util/qdeclarativebehavior.cpp230
-rw-r--r--src/declarative/util/qdeclarativebehavior_p.h98
-rw-r--r--src/declarative/util/qdeclarativebind.cpp214
-rw-r--r--src/declarative/util/qdeclarativebind_p.h96
-rw-r--r--src/declarative/util/qdeclarativeconnections.cpp289
-rw-r--r--src/declarative/util/qdeclarativeconnections_p.h103
-rw-r--r--src/declarative/util/qdeclarativefontloader.cpp338
-rw-r--r--src/declarative/util/qdeclarativefontloader_p.h97
-rw-r--r--src/declarative/util/qdeclarativelistaccessor.cpp138
-rw-r--r--src/declarative/util/qdeclarativelistaccessor_p.h80
-rw-r--r--src/declarative/util/qdeclarativelistmodel.cpp1628
-rw-r--r--src/declarative/util/qdeclarativelistmodel_p.h158
-rw-r--r--src/declarative/util/qdeclarativelistmodel_p_p.h281
-rw-r--r--src/declarative/util/qdeclarativelistmodelworkeragent.cpp278
-rw-r--r--src/declarative/util/qdeclarativelistmodelworkeragent_p.h163
-rw-r--r--src/declarative/util/qdeclarativenullablevalue_p_p.h81
-rw-r--r--src/declarative/util/qdeclarativeopenmetaobject.cpp380
-rw-r--r--src/declarative/util/qdeclarativeopenmetaobject_p.h129
-rw-r--r--src/declarative/util/qdeclarativepackage.cpp201
-rw-r--r--src/declarative/util/qdeclarativepackage_p.h98
-rw-r--r--src/declarative/util/qdeclarativepixmapcache.cpp1119
-rw-r--r--src/declarative/util/qdeclarativepixmapcache_p.h124
-rw-r--r--src/declarative/util/qdeclarativepropertychanges.cpp798
-rw-r--r--src/declarative/util/qdeclarativepropertychanges_p.h112
-rw-r--r--src/declarative/util/qdeclarativepropertymap.cpp296
-rw-r--r--src/declarative/util/qdeclarativepropertymap.h90
-rw-r--r--src/declarative/util/qdeclarativesmoothedanimation.cpp493
-rw-r--r--src/declarative/util/qdeclarativesmoothedanimation_p.h103
-rw-r--r--src/declarative/util/qdeclarativesmoothedanimation_p_p.h135
-rw-r--r--src/declarative/util/qdeclarativespringanimation.cpp462
-rw-r--r--src/declarative/util/qdeclarativespringanimation_p.h111
-rw-r--r--src/declarative/util/qdeclarativestate.cpp742
-rw-r--r--src/declarative/util/qdeclarativestate_p.h210
-rw-r--r--src/declarative/util/qdeclarativestate_p_p.h255
-rw-r--r--src/declarative/util/qdeclarativestategroup.cpp502
-rw-r--r--src/declarative/util/qdeclarativestategroup_p.h95
-rw-r--r--src/declarative/util/qdeclarativestateoperations.cpp1587
-rw-r--r--src/declarative/util/qdeclarativestateoperations_p.h299
-rw-r--r--src/declarative/util/qdeclarativestyledtext.cpp347
-rw-r--r--src/declarative/util/qdeclarativestyledtext_p.h69
-rw-r--r--src/declarative/util/qdeclarativesystempalette.cpp312
-rw-r--r--src/declarative/util/qdeclarativesystempalette_p.h122
-rw-r--r--src/declarative/util/qdeclarativetimeline.cpp947
-rw-r--r--src/declarative/util/qdeclarativetimeline_p_p.h200
-rw-r--r--src/declarative/util/qdeclarativetimer.cpp324
-rw-r--r--src/declarative/util/qdeclarativetimer_p.h115
-rw-r--r--src/declarative/util/qdeclarativetransition.cpp345
-rw-r--r--src/declarative/util/qdeclarativetransition_p.h106
-rw-r--r--src/declarative/util/qdeclarativetransitionmanager.cpp276
-rw-r--r--src/declarative/util/qdeclarativetransitionmanager_p_p.h85
-rw-r--r--src/declarative/util/qdeclarativeutilmodule.cpp174
-rw-r--r--src/declarative/util/qdeclarativeutilmodule_p.h63
-rw-r--r--src/declarative/util/qdeclarativeview.cpp739
-rw-r--r--src/declarative/util/qdeclarativeview.h119
-rw-r--r--src/declarative/util/qdeclarativexmllistmodel.cpp1157
-rw-r--r--src/declarative/util/qdeclarativexmllistmodel_p.h213
-rw-r--r--src/declarative/util/qlistmodelinterface.cpp105
-rw-r--r--src/declarative/util/qlistmodelinterface_p.h84
-rw-r--r--src/declarative/util/util.pri72
333 files changed, 132839 insertions, 0 deletions
diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt
new file mode 100644
index 00000000..6e073305
--- /dev/null
+++ b/src/declarative/QmlChanges.txt
@@ -0,0 +1,364 @@
+=============================================================================
+The changes below are pre Qt 4.7.0 RC1
+
+TextInput
+ - copy(), cut() and paste() functions added
+Font.letterSpacing
+ - was percentage based. Now specified in pixels.
+Item
+ - wantsFocus renamed to activeFocus
+ - forceFocus() renamed to forceActiveFocus()
+ - focus now returns the scoped focus (i.e. focus read/write now manipulate
+ the same value)
+TextInput and TextEdit:
+ - focusOnPress renamed to activeFocusOnPress
+
+=============================================================================
+The changes below are pre Qt 4.7.0 beta 2
+
+QDeclarativeView
+ - initialSize() function added
+TextInput and TextEdit:
+ - openSoftwareInputPanel() and closeSoftwareInputPanel() functions added
+Flickable:
+ - overShoot is replaced by boundsBehavior enumeration
+ - flickingHorizontally and flickingVertically properties added
+ - movingHorizontally and movingVertically properties added
+ - flickDirection is renamed flickableDirection
+Component:
+ - isReady, isLoading, isError and isNull properties removed, use
+ status property instead
+ - errorsString() renamed to errorString()
+ListView:
+ - ListView.prevSection property changed to ListView.previousSection
+TextInput:
+ - xToPosition -> positionAt (to match TextEdit.positionAt)
+Image:
+ - pixmap property removed, use QDeclarativeImageProvider to serve pixmaps
+ instead
+
+QList<QObject*> models no longer provide properties in model object. The
+properties are now updated when the object changes. An object's property
+"foo" may now be accessed as "foo", modelData.foo" or model.modelData.foo"
+component.createObject has gained a mandatory "parent" argument
+TextEdit and TextInput now have a "selectByMouse" property that defaults to false.
+
+C++ API
+-------
+QDeclarativeExpression::value() has been renamed to
+QDeclarativeExpression::evaluate()
+
+The QDeclarativeExpression constructor has changed from
+ QDeclarativeExpression(context, expression, scope)
+to
+ QDeclarativeExpression(context, scope, expression, parent = 0)
+
+QDeclarativeImageProvider::request() has been renamed to
+QDeclarativeImageProvider::image() and the class can now provide
+both qimages and qpixmaps, and qimages can be served synchronously
+
+QML Viewer
+------------
+The standalone qml executable has been renamed back to Qml Viewer. Runtime warnings
+can be now accessed via the menu (Debugging->Show Warnings).
+
+=============================================================================
+The changes below are pre Qt 4.7.0 beta 1
+
+TextEdit: wrap property is replaced by wrapMode enumeration.
+Text: wrap property is replaced by wrapMode enumeration.
+Removed Q-prefix from validators (IntValidator, DoubleValidator, and RegExpValidator)
+PathView: offset property now uses range 0-1.0 rather than 0-100
+ListView, GridView::positionViewAtIndex() gained a 'mode' parameter
+Removed Qt.playSound (replaced by SoundEffect element)
+Removed Qt.closestAngle (use RotationAnimation instead)
+Removed NumberFormatter
+Removed DateTimeFormatter (use Qt.formatDateTime() instead)
+Using WebView now requires "import QtWebKit 1.0"
+Using Particles now requires "import Qt.labs.particles 1.0"
+AnchorAnimation must now be used to animate anchor changes (and not NumberAnimation)
+Removed ParentAction (use ParentAnimation instead)
+ScriptAction: renamed stateChangeScriptName -> scriptName
+Animation: replace repeat with loops (loops: Animation.Infinite gives the old repeat behavior)
+AnchorChanges: use natural form to specify anchors (anchors.left instead of left)
+AnchorChanges: removed reset property. (reset: "left" should now be anchors.left: undefined)
+PathView: snapPosition replaced by preferredHighlightBegin, preferredHighlightEnd
+createQmlObject: Moved to the Qt object, now use Qt.createQmlObject()
+createComponent: Moved to the Qt object, now use Qt.createComponent()
+
+C++ API
+-------
+QDeclarativeContext::addDefaultObject() has been replaced with
+QDeclarativeContext::setContextObject()
+
+Behavior and Animation syntax
+-----------------------------
+Previously animations and behaviors could be "assigned" to properties like this:
+ Item { x: Behavior {}; y: NumberAnimation {} }
+To make it more obvious that these are not regular value assignments a new "on"
+syntax has been introduced:
+ Item { Behavior on x {}; NumberAnimation on y {} }
+Only the syntax has changed, the behavior is identical.
+
+EaseFollow renamed to SmoothedFollow
+---------------------------------------
+This element shares the internal implementation with SmoothedAnimation,
+both providing the same easing function, but with SmoothedFollow it's
+easier to set a start value to animate intially and then start to follow,
+while SmoothedAnimation is still convenient for using inside Behaviors
+and Transitions.
+
+
+Add SmoothedAnimation element
+---------------------------------------
+SmoothedAnimation inherits from NumberAnimaton and as a
+consequence SmoothedAnimation can be used inside Behaviors,
+as PropertySourceValues or in state transitions, like any other animation.
+
+The old EaseFollow properties changed to comply with the other declarative
+animations ('source' changed to 'to'), so now 'to' changes are not
+automatically 'followed' anymore.
+
+If you want to follow an hypothetical rect1, you should do now:
+
+ Rectangle {
+ color: "green"
+ width: 60; height: 60;
+ x: rect1.x - 5; y: rect1.y - 5;
+ Behavior on x { SmoothedAnimation { velocity: 200 } }
+ Behavior on y { SmoothedAnimation { velocity: 200 } }
+ }
+
+instead of the old automatic source changed tracking:
+
+ Rectangle {
+ color: "green"
+ width: 60; height: 60;
+ EaseFollow on x { source: rect1.x - 5; velocity: 200 }
+ EaseFollow on y { source: rect1.y - 5; velocity: 200 }
+ }
+
+This is a syntax and behavior change.
+
+
+Script element removed
+----------------------
+Inline Script{} blocks have been deprecated, and will soon be removed entirely.
+If you used Script to write inline javascript code, it can simply be removed.
+For example
+
+Item {
+ Script {
+ function doSomething() {}
+ }
+}
+
+becomes
+
+Item {
+ function doSomething() {}
+}
+
+If you used Script to include external JavaScript files, you can replace the
+Script element with an “import” line. For example
+
+MouseArea {
+ Script {
+ source: “foo.js”
+ }
+ onClicked: foo()
+}
+
+becomes
+
+import “foo.js” as Foo
+MouseArea {
+ onClicked: Foo.foo()
+}
+
+The “as” qualifier is mandatory for script imports (as opposed to type
+imports where it is optional).
+
+
+=============================================================================
+The changes below are pre Qt 4.7.0 alpha
+
+Flickable: renamed viewportWidth -> contentWidth
+Flickable: renamed viewportHeight -> contentHeight
+Flickable: renamed viewportX -> contentX
+Flickable: renamed viewportY -> contentY
+Removed Flickable.reportedVelocitySmoothing
+Renamed MouseRegion -> MouseArea
+Connection: syntax and rename:
+ Connection { sender: a; signal: foo(); script: xxx }
+ Connection { sender: a; signal: bar(); script: yyy }
+ becomes:
+ Connections { target: a; onFoo: xxx; onBar: yyy }
+
+ListView::sectionExpression has been replaced by section.property, section.criteria
+
+ListModel
+---------
+- types are strictly checked (previously, everything was a string)
+ - foo: "bar" continues to work as before
+ - foo: bar is now invalid, use foo: "bar"
+ - foo: true is now a bool (not string "true")
+ - foo: false is now a bool (not string "false" == true!)
+
+PropertyAnimation
+------------------
+matchProperties and matchTargets have been renamed back to properties and targets.
+The semantics are explained in the PropertyAnimation::properties documentation
+and the animation overview documentation.
+
+Easing curves and their parameters are now specified via dot properties:
+* easing.type : enum
+* easing.amplitude : real
+* easing.overshoot : real
+* easing.period : real
+For example:
+PropertyAnimation { properties: "y"; easing.type: "InOutElastic"; easing.amplitude: 2.0; easing.period: 1.5 }
+
+C++ API
+-------
+QML_DEFINE_... definition macros, previously global macros, are replaced by
+qmlRegisterType registration functions, which must be called explicitly.
+C++ API users should also consider using the QmlExtensionPlugin (previously
+named QmlModulePlugin) as a cleaner mechanism for publishing libraries of QML
+types, or the upcoming application plugin features of the qmlviewer /
+qmlruntime / qml.
+
+QmlView
+-------
+The API of QmlView has been narrowed and its role as a convenience class
+reinforced.
+- remove addItem()
+- remove clearItems() - use 'delete root()'
+- remove reset()
+- resizeContent -> enum ResizeMode { SizeViewToRootObject, SizeRootObjectToView }
+- remove setQml(), qml()
+- rename setUrl(), ur() to setSource(), source()
+- root() -> rootObject(), returns QGraphicsObject rather than QmlGraphicsItem
+- remove quit() signal -> use quit() signal of engine()
+- initialSize() signal removed
+- Added status() to determine status of the internal QmlComponent
+- removed execute() - setSource() will also execute the QML.
+
+
+=============================================================================
+The changes below are pre-4.6.0 release.
+
+QML API Review
+==============
+
+The QML API is being reviewed. This file documents the changes.
+Note that the changes are incremental, so a rename A->B for example may be followed
+by another subsequent rename B->C, if later reviews override earlier reviews.
+
+API Changes
+===========
+
+Renamed Elements:
+LineEdit -> TextInput
+VerticalLayout -> Column
+HorizontalLayout -> Row
+VerticalPositioner -> Column
+HorizontalPositioner -> Row
+GridLayout -> Grid
+GridPositioner -> Grid
+Rect -> Rectangle
+FocusRealm -> FocusScope
+FontFamily -> FontLoader
+Palette -> SystemPalette
+Bind -> Binding
+SetProperties -> PropertyChanges
+RunScript -> StateChangeScript
+SetAnchors -> AnchorChanges
+SetPropertyAction -> PropertyAction
+RunScriptAction -> ScriptAction
+ParentChangeAction -> ParentAction
+VisualModel -> VisualDataModel
+Follow -> SpringFollow
+
+Renamed properties:
+Item: contents -> childrenRect
+MouseRegion: xmin -> minimumX
+MouseRegion: xmax -> maximumX
+MouseRegion: ymin -> minimumY
+MouseRegion: ymin -> maximumY
+Text elements: hAlign -> horizontalAlignment
+Text elements: vAlign -> verticalAlignment
+Text elements: highlightColor -> selectionColor
+Text elements: highlightedTextColor -> selectedTextColor
+Text elements: preserveSelection -> persistentSelection
+State: operations -> changes
+Transition: operations -> animations
+Transition: fromState -> from
+Transition: toState -> to
+Follow: followValue -> value
+Flickable: xPosition -> viewportX
+Flickable: yPosition -> viewportY
+Flickable: xVelocity -> horizontalVelocity
+Flickable: yVelocity -> verticalVelocity
+Flickable: velocityDecay -> reportedVelocitySmoothing
+Flickable: locked -> interactive (note reversal of meaning)
+Flickable: pageXPosition -> visibleArea.xPosition
+Flickable: pageYPosition -> visibleArea.yPosition
+Flickable: pageWidth -> visibleArea.widthRatio
+Flickable: pageHeight -> visibleArea.heightRatio
+WebView: idealWidth -> preferredWidth
+WebView: idealHeight -> preferredHeight
+WebView: status -> statusText
+WebView: mouseX -> clickX (parameter to onDoubleClick)
+WebView: mouseY -> clickY (parameter to onDoubleClick)
+WebView: cacheSize -> pixelCacheSize
+Repeater: component -> delegate
+Repeater: dataSource -> model
+ListView: current -> currentItem
+GridView: current -> currentItem
+ListView: wrap -> keyNavigationWraps
+ListView: autoHighlight -> highlightFollowsCurrentItem
+GridView: wrap -> keyNavigationWraps
+GridView: autoHighlight -> highlightFollowsCurrentItem
+Animation: targets -> matchTargets
+Animation: properties -> matchProperties
+
+Additions:
+MouseRegion: add "acceptedButtons" property
+MouseRegion: add "hoverEnabled" property
+MouseRegion: add "pressedButtons" property
+Timer: add start() and stop() slots
+WebView: add newWindowComponent and newWindowParent properties
+Loader: add status() and progress() properties
+Loader: add sourceComponent property
+Loader: add resizeMode property
+ListView: preferredHighlightBegin, preferredHighlightEnd
+ListView: strictlyEnforceHighlightRange
+Particles: Added emissionRate, emissionVariance and burst()
+
+Deletions:
+Column/VerticalPositioner: lost "margins" property
+Row/HorizontalPositioner: lost "margins" property
+Grid/Positioner/Layout: lost "margins" property
+WebView: lost "interactive" property (always true now)
+Flickable: removed "dragMode" property
+ComponentInstance: removed. Replaced by Loader.sourceComponent
+ListView: removed currentItemMode. Replaced by highligh range.
+ListView: removed snapPos.
+Particles: removed streamIn. Replaced by emissionRate
+
+Other Changes:
+ids must be lowercase: Text { id: foo }, not Text { id: Foo }
+Drag: axis becomes an enum with values "XAxis", "YAxis", "XandYAxis"
+Image: scaleGrid property removed. New item called BorderImage instead.
+KeyActions: changed to a Keys attached property on any item.
+KeyProxy: changed to a Keys.forwardTo property on any item.
+Script: now an intrinsic type in the language
+ - cannot be assigned to properties
+ - good: Item { Script { ... } }
+ - bad: Item { resources: Script { ... } }
+Script: delay-loaded of the QML file until their source has been loaded (this only effects QML files loaded across the network.)
+Scope: declared properties shadow a property of the same name (was previously the reverse)
+ScriptAction and StateChangeScript: the script property now takes script rather than a string containing script (script: doSomething() rather than script: "doSomething()")
+QmlGraphicsItem::transformOrigin default changed from TopLeft to Center
+Animations used as PropertySourceValues are set to 'running: true' as default
diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri
new file mode 100644
index 00000000..c81968ee
--- /dev/null
+++ b/src/declarative/debugger/debugger.pri
@@ -0,0 +1,33 @@
+INCLUDEPATH += $$PWD
+
+SOURCES += \
+ $$PWD/qdeclarativedebuggerstatus.cpp \
+ $$PWD/qpacketprotocol.cpp \
+ $$PWD/qdeclarativedebugservice.cpp \
+ $$PWD/qdeclarativedebugclient.cpp \
+ $$PWD/qdeclarativeenginedebug.cpp \
+ $$PWD/qdeclarativedebugtrace.cpp \
+ $$PWD/qdeclarativedebughelper.cpp \
+ $$PWD/qdeclarativedebugserver.cpp \
+ $$PWD/qdeclarativeinspectorservice.cpp \
+ $$PWD/qjsdebuggeragent.cpp \
+ $$PWD/qjsdebugservice.cpp \
+ $$PWD/qdeclarativeenginedebugservice.cpp
+
+HEADERS += \
+ $$PWD/qdeclarativedebuggerstatus_p.h \
+ $$PWD/qpacketprotocol_p.h \
+ $$PWD/qdeclarativedebugservice_p.h \
+ $$PWD/qdeclarativedebugservice_p_p.h \
+ $$PWD/qdeclarativedebugclient_p.h \
+ $$PWD/qdeclarativeenginedebug_p.h \
+ $$PWD/qdeclarativedebugtrace_p.h \
+ $$PWD/qdeclarativedebughelper_p.h \
+ $$PWD/qdeclarativedebugserver_p.h \
+ $$PWD/qdeclarativedebugserverconnection_p.h \
+ $$PWD/qdeclarativeinspectorservice_p.h \
+ $$PWD/qdeclarativeinspectorinterface_p.h \
+ $$PWD/qjsdebuggeragent_p.h \
+ $$PWD/qjsdebugservice_p.h \
+ $$PWD/qdeclarativedebug.h \
+ $$PWD/qdeclarativeenginedebugservice_p.h
diff --git a/src/declarative/debugger/qdeclarativedebug.h b/src/declarative/debugger/qdeclarativedebug.h
new file mode 100644
index 00000000..8b0a65c2
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebug.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEDEBUG_H
+#define QDECLARATIVEDEBUG_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+struct Q_DECLARATIVE_EXPORT QDeclarativeDebuggingEnabler
+{
+ QDeclarativeDebuggingEnabler();
+};
+
+// Execute code in constructor before first QDeclarativeEngine is instantiated
+#if defined(QT_DECLARATIVE_DEBUG)
+static QDeclarativeDebuggingEnabler qmlEnableDebuggingHelper;
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEDEBUG_H
diff --git a/src/declarative/debugger/qdeclarativedebugclient.cpp b/src/declarative/debugger/qdeclarativedebugclient.cpp
new file mode 100644
index 00000000..9c3d8144
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebugclient.cpp
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativedebugclient_p.h"
+
+#include "private/qpacketprotocol_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+const int protocolVersion = 1;
+const QString serverId = QLatin1String("QDeclarativeDebugServer");
+const QString clientId = QLatin1String("QDeclarativeDebugClient");
+
+class QDeclarativeDebugClientPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarativeDebugClient)
+public:
+ QDeclarativeDebugClientPrivate();
+
+ QString name;
+ QDeclarativeDebugConnection *connection;
+};
+
+class QDeclarativeDebugConnectionPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c);
+ QDeclarativeDebugConnection *q;
+ QPacketProtocol *protocol;
+
+ bool gotHello;
+ QStringList serverPlugins;
+ QHash<QString, QDeclarativeDebugClient *> plugins;
+
+ void advertisePlugins();
+
+public Q_SLOTS:
+ void connected();
+ void readyRead();
+};
+
+QDeclarativeDebugConnectionPrivate::QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c)
+: QObject(c), q(c), protocol(0), gotHello(false)
+{
+ protocol = new QPacketProtocol(q, this);
+ QObject::connect(c, SIGNAL(connected()), this, SLOT(connected()));
+ QObject::connect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
+}
+
+void QDeclarativeDebugConnectionPrivate::advertisePlugins()
+{
+ if (!q->isConnected())
+ return;
+
+ QPacket pack;
+ pack << serverId << 1 << plugins.keys();
+ protocol->send(pack);
+ q->flush();
+}
+
+void QDeclarativeDebugConnectionPrivate::connected()
+{
+ QPacket pack;
+ pack << serverId << 0 << protocolVersion << plugins.keys();
+ protocol->send(pack);
+ q->flush();
+}
+
+void QDeclarativeDebugConnectionPrivate::readyRead()
+{
+ if (!gotHello) {
+ QPacket pack = protocol->read();
+ QString name;
+
+ pack >> name;
+
+ bool validHello = false;
+ if (name == clientId) {
+ int op = -1;
+ pack >> op;
+ if (op == 0) {
+ int version = -1;
+ pack >> version;
+ if (version == protocolVersion) {
+ pack >> serverPlugins;
+ validHello = true;
+ }
+ }
+ }
+
+ if (!validHello) {
+ qWarning("QDeclarativeDebugConnection: Invalid hello message");
+ QObject::disconnect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
+ return;
+ }
+
+ gotHello = true;
+
+ QHash<QString, QDeclarativeDebugClient *>::Iterator iter = plugins.begin();
+ for (; iter != plugins.end(); ++iter) {
+ QDeclarativeDebugClient::Status newStatus = QDeclarativeDebugClient::Unavailable;
+ if (serverPlugins.contains(iter.key()))
+ newStatus = QDeclarativeDebugClient::Enabled;
+ iter.value()->statusChanged(newStatus);
+ }
+ }
+
+ while (protocol->packetsAvailable()) {
+ QPacket pack = protocol->read();
+ QString name;
+ pack >> name;
+
+ if (name == clientId) {
+ int op = -1;
+ pack >> op;
+
+ if (op == 1) {
+ // Service Discovery
+ QStringList oldServerPlugins = serverPlugins;
+ pack >> serverPlugins;
+
+ QHash<QString, QDeclarativeDebugClient *>::Iterator iter = plugins.begin();
+ for (; iter != plugins.end(); ++iter) {
+ const QString pluginName = iter.key();
+ QDeclarativeDebugClient::Status newStatus = QDeclarativeDebugClient::Unavailable;
+ if (serverPlugins.contains(pluginName))
+ newStatus = QDeclarativeDebugClient::Enabled;
+
+ if (oldServerPlugins.contains(pluginName)
+ != serverPlugins.contains(pluginName)) {
+ iter.value()->statusChanged(newStatus);
+ }
+ }
+ } else {
+ qWarning() << "QDeclarativeDebugConnection: Unknown control message id" << op;
+ }
+ } else {
+ QByteArray message;
+ pack >> message;
+
+ QHash<QString, QDeclarativeDebugClient *>::Iterator iter =
+ plugins.find(name);
+ if (iter == plugins.end()) {
+ qWarning() << "QDeclarativeDebugConnection: Message received for missing plugin" << name;
+ } else {
+ (*iter)->messageReceived(message);
+ }
+ }
+ }
+}
+
+QDeclarativeDebugConnection::QDeclarativeDebugConnection(QObject *parent)
+: QTcpSocket(parent), d(new QDeclarativeDebugConnectionPrivate(this))
+{
+}
+
+QDeclarativeDebugConnection::~QDeclarativeDebugConnection()
+{
+ QHash<QString, QDeclarativeDebugClient*>::iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter) {
+ iter.value()->d_func()->connection = 0;
+ iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected);
+ }
+}
+
+bool QDeclarativeDebugConnection::isConnected() const
+{
+ return state() == ConnectedState;
+}
+
+QDeclarativeDebugClientPrivate::QDeclarativeDebugClientPrivate()
+: connection(0)
+{
+}
+
+QDeclarativeDebugClient::QDeclarativeDebugClient(const QString &name,
+ QDeclarativeDebugConnection *parent)
+: QObject(*(new QDeclarativeDebugClientPrivate), parent)
+{
+ Q_D(QDeclarativeDebugClient);
+ d->name = name;
+ d->connection = parent;
+
+ if (!d->connection)
+ return;
+
+ if (d->connection->d->plugins.contains(name)) {
+ qWarning() << "QDeclarativeDebugClient: Conflicting plugin name" << name;
+ d->connection = 0;
+ } else {
+ d->connection->d->plugins.insert(name, this);
+ d->connection->d->advertisePlugins();
+ }
+}
+
+QDeclarativeDebugClient::~QDeclarativeDebugClient()
+{
+ Q_D(const QDeclarativeDebugClient);
+ if (d->connection && d->connection->d) {
+ d->connection->d->plugins.remove(d->name);
+ d->connection->d->advertisePlugins();
+ }
+}
+
+QString QDeclarativeDebugClient::name() const
+{
+ Q_D(const QDeclarativeDebugClient);
+ return d->name;
+}
+
+QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const
+{
+ Q_D(const QDeclarativeDebugClient);
+ if (!d->connection
+ || !d->connection->isConnected()
+ || !d->connection->d->gotHello)
+ return NotConnected;
+
+ if (d->connection->d->serverPlugins.contains(d->name))
+ return Enabled;
+
+ return Unavailable;
+}
+
+void QDeclarativeDebugClient::sendMessage(const QByteArray &message)
+{
+ Q_D(QDeclarativeDebugClient);
+
+ if (status() != Enabled)
+ return;
+
+ QPacket pack;
+ pack << d->name << message;
+ d->connection->d->protocol->send(pack);
+ d->connection->d->q->flush();
+}
+
+void QDeclarativeDebugClient::statusChanged(Status)
+{
+}
+
+void QDeclarativeDebugClient::messageReceived(const QByteArray &)
+{
+}
+
+QT_END_NAMESPACE
+
+#include <qdeclarativedebugclient.moc>
diff --git a/src/declarative/debugger/qdeclarativedebugclient_p.h b/src/declarative/debugger/qdeclarativedebugclient_p.h
new file mode 100644
index 00000000..ea099fe2
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebugclient_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEDEBUGCLIENT_H
+#define QDECLARATIVEDEBUGCLIENT_H
+
+#include <QtNetwork/qtcpsocket.h>
+
+#include <private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeDebugConnectionPrivate;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugConnection : public QTcpSocket
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QDeclarativeDebugConnection)
+public:
+ QDeclarativeDebugConnection(QObject * = 0);
+ ~QDeclarativeDebugConnection();
+
+ bool isConnected() const;
+private:
+ QDeclarativeDebugConnectionPrivate *d;
+ friend class QDeclarativeDebugClient;
+ friend class QDeclarativeDebugClientPrivate;
+};
+
+class QDeclarativeDebugClientPrivate;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugClient : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeDebugClient)
+ Q_DISABLE_COPY(QDeclarativeDebugClient)
+
+public:
+ enum Status { NotConnected, Unavailable, Enabled };
+
+ QDeclarativeDebugClient(const QString &, QDeclarativeDebugConnection *parent);
+ ~QDeclarativeDebugClient();
+
+ QString name() const;
+
+ Status status() const;
+
+ void sendMessage(const QByteArray &);
+
+protected:
+ virtual void statusChanged(Status);
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ friend class QDeclarativeDebugConnection;
+ friend class QDeclarativeDebugConnectionPrivate;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEDEBUGCLIENT_H
diff --git a/src/declarative/debugger/qdeclarativedebuggerstatus.cpp b/src/declarative/debugger/qdeclarativedebuggerstatus.cpp
new file mode 100644
index 00000000..2e2f4f5b
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebuggerstatus.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativedebuggerstatus_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QDeclarativeDebuggerStatus::~QDeclarativeDebuggerStatus()
+{
+}
+
+void QDeclarativeDebuggerStatus::setSelectedState(bool)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativedebuggerstatus_p.h b/src/declarative/debugger/qdeclarativedebuggerstatus_p.h
new file mode 100644
index 00000000..0404e0f8
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebuggerstatus_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEDEBUGGERSTATUS_P_H
+#define QDECLARATIVEDEBUGGERSTATUS_P_H
+
+#include <QtCore/qobject.h>
+
+#include <private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebuggerStatus
+{
+public:
+ virtual ~QDeclarativeDebuggerStatus();
+
+ virtual void setSelectedState(bool);
+};
+Q_DECLARE_INTERFACE(QDeclarativeDebuggerStatus, "com.trolltech.qml.QDeclarativeDebuggerStatus")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLMDEBUGGERSTATUS_P_H
diff --git a/src/declarative/debugger/qdeclarativedebughelper.cpp b/src/declarative/debugger/qdeclarativedebughelper.cpp
new file mode 100644
index 00000000..1a460bfb
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebughelper.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 <QtScript/QScriptEngine>
+
+#include "private/qdeclarativedebughelper_p.h"
+
+#include <QtCore/QAbstractAnimation>
+#include <QtScript/QScriptEngine>
+
+#include <private/qdeclarativeengine_p.h>
+#include <private/qabstractanimation_p.h>
+#include <private/qdeclarativeengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QScriptEngine *QDeclarativeDebugHelper::getScriptEngine(QDeclarativeEngine *engine)
+{
+ return QDeclarativeEnginePrivate::getScriptEngine(engine);
+}
+
+void QDeclarativeDebugHelper::setAnimationSlowDownFactor(qreal factor)
+{
+ QUnifiedTimer *timer = QUnifiedTimer::instance();
+ timer->setSlowModeEnabled(factor != 1.0);
+ timer->setSlowdownFactor(factor);
+}
+
+void QDeclarativeDebugHelper::enableDebugging() {
+#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
+ if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
+ qWarning("Qml debugging is enabled. Only use this in a safe environment!");
+ }
+ QDeclarativeEnginePrivate::qml_debugging_enabled = true;
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativedebughelper_p.h b/src/declarative/debugger/qdeclarativedebughelper_p.h
new file mode 100644
index 00000000..93370982
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebughelper_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEDEBUGHELPER_P_H
+#define QDECLARATIVEDEBUGHELPER_P_H
+
+#include <QtCore/qglobal.h>
+
+#include <private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QScriptEngine;
+class QDeclarativeEngine;
+
+// Helper methods to access private API through a stable interface
+// This is used in the qmljsdebugger library of QtCreator.
+class Q_DECLARATIVE_EXPORT QDeclarativeDebugHelper
+{
+public:
+ static QScriptEngine *getScriptEngine(QDeclarativeEngine *engine);
+ static void setAnimationSlowDownFactor(qreal factor);
+
+ // Enables remote debugging functionality
+ // Only use this for debugging in a safe environment!
+ static void enableDebugging();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEDEBUGHELPER_P_H
diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp
new file mode 100644
index 00000000..c664f960
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebugserver.cpp
@@ -0,0 +1,426 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativedebugserver_p.h"
+#include "private/qdeclarativedebugservice_p.h"
+#include "private/qdeclarativedebugservice_p_p.h"
+#include "private/qdeclarativeengine_p.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QPluginLoader>
+#include <QtCore/QStringList>
+
+#include <private/qobject_p.h>
+#include <private/qapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ QDeclarativeDebug Protocol (Version 1):
+
+ handshake:
+ 1. Client sends
+ "QDeclarativeDebugServer" 0 version pluginNames
+ version: an int representing the highest protocol version the client knows
+ pluginNames: plugins available on client side
+ 2. Server sends
+ "QDeclarativeDebugClient" 0 version pluginNames
+ version: an int representing the highest protocol version the client & server know
+ pluginNames: plugins available on server side. plugins both in the client and server message are enabled.
+ client plugin advertisement
+ 1. Client sends
+ "QDeclarativeDebugServer" 1 pluginNames
+ server plugin advertisement
+ 1. Server sends
+ "QDeclarativeDebugClient" 1 pluginNames
+ plugin communication:
+ Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin.
+ */
+
+const int protocolVersion = 1;
+
+
+class QDeclarativeDebugServerPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarativeDebugServer)
+public:
+ QDeclarativeDebugServerPrivate();
+
+ void advertisePlugins();
+
+ QDeclarativeDebugServerConnection *connection;
+ QHash<QString, QDeclarativeDebugService *> plugins;
+ QStringList clientPlugins;
+ bool gotHello;
+ QString waitingForMsgFromService;
+ bool waitingForMsgSucceeded;
+
+private:
+ // private slot
+ void _q_deliverMessage(const QString &serviceName, const QByteArray &message);
+ static QDeclarativeDebugServerConnection *loadConnectionPlugin(QPluginLoader *loader, const QString &pluginName);
+};
+
+QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() :
+ connection(0),
+ gotHello(false),
+ waitingForMsgSucceeded(false)
+{
+}
+
+void QDeclarativeDebugServerPrivate::advertisePlugins()
+{
+ if (!gotHello)
+ return;
+
+ QByteArray message;
+ {
+ QDataStream out(&message, QIODevice::WriteOnly);
+ out << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys();
+ }
+ connection->send(message);
+}
+
+QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectionPlugin(
+ QPluginLoader *loader, const QString &pluginName)
+{
+#ifndef QT_NO_LIBRARY
+ QStringList pluginCandidates;
+ const QStringList paths = QCoreApplication::libraryPaths();
+ foreach (const QString &libPath, paths) {
+ const QDir dir(libPath + QLatin1String("/qmltooling"));
+ if (dir.exists()) {
+ QStringList plugins(dir.entryList(QDir::Files));
+ foreach (const QString &pluginPath, plugins) {
+ if (QFileInfo(pluginPath).fileName().contains(pluginName))
+ pluginCandidates << dir.absoluteFilePath(pluginPath);
+ }
+ }
+ }
+
+ foreach (const QString &pluginPath, pluginCandidates) {
+ loader->setFileName(pluginPath);
+ if (!loader->load()) {
+ continue;
+ }
+ QDeclarativeDebugServerConnection *connection = 0;
+ if (QObject *instance = loader->instance())
+ connection = qobject_cast<QDeclarativeDebugServerConnection*>(instance);
+
+ if (connection)
+ return connection;
+ loader->unload();
+ }
+#endif
+ return 0;
+}
+
+bool QDeclarativeDebugServer::hasDebuggingClient() const
+{
+ Q_D(const QDeclarativeDebugServer);
+ return d->connection
+ && d->connection->isConnected()
+ && d->gotHello;
+}
+
+QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
+{
+ static bool commandLineTested = false;
+ static QDeclarativeDebugServer *server = 0;
+
+ if (!commandLineTested) {
+ commandLineTested = true;
+
+ QApplicationPrivate *appD = static_cast<QApplicationPrivate*>(QObjectPrivate::get(qApp));
+#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
+ // ### remove port definition when protocol is changed
+ int port = 0;
+ bool block = false;
+ bool ok = false;
+
+ // format: qmljsdebugger=port:3768[,block] OR qmljsdebugger=ost[,block]
+ if (!appD->qmljsDebugArgumentsString().isEmpty()) {
+ if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
+ qWarning() << QString::fromLatin1(
+ "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
+ "Debugging has not been enabled.").arg(
+ appD->qmljsDebugArgumentsString());
+ return 0;
+ }
+
+ QString pluginName;
+ if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) {
+ int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(','));
+ port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok);
+ pluginName = QLatin1String("qmldbg_tcp");
+ } else if (appD->qmljsDebugArgumentsString().contains(QLatin1String("ost"))) {
+ pluginName = QLatin1String("qmldbg_ost");
+ ok = true;
+ }
+
+ block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block"));
+
+ if (ok) {
+ server = new QDeclarativeDebugServer();
+
+ QPluginLoader *loader = new QPluginLoader(server);
+ QDeclarativeDebugServerConnection *connection
+ = QDeclarativeDebugServerPrivate::loadConnectionPlugin(loader, pluginName);
+ if (connection) {
+ server->d_func()->connection = connection;
+
+ connection->setServer(server);
+ connection->setPort(port, block);
+ } else {
+ qWarning() << QString::fromLatin1(
+ "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
+ "Remote debugger plugin has not been found.").arg(
+ appD->qmljsDebugArgumentsString());
+ }
+
+ } else {
+ qWarning() << QString::fromLatin1(
+ "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
+ "Format is -qmljsdebugger=port:<port>[,block]").arg(
+ appD->qmljsDebugArgumentsString());
+ }
+ }
+#else
+ if (!appD->qmljsDebugArgumentsString().isEmpty()) {
+ qWarning() << QString::fromLatin1(
+ "QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
+ "QtDeclarative is not configured for debugging.").arg(
+ appD->qmljsDebugArgumentsString());
+ }
+#endif
+ }
+
+ return server;
+}
+
+QDeclarativeDebugServer::QDeclarativeDebugServer()
+: QObject(*(new QDeclarativeDebugServerPrivate))
+{
+}
+
+void QDeclarativeDebugServer::receiveMessage(const QByteArray &message)
+{
+ Q_D(QDeclarativeDebugServer);
+
+ QDataStream in(message);
+ if (!d->gotHello) {
+ QString name;
+ int op;
+ in >> name >> op;
+
+ if (name != QLatin1String("QDeclarativeDebugServer")
+ || op != 0) {
+ qWarning("QDeclarativeDebugServer: Invalid hello message");
+ d->connection->disconnect();
+ return;
+ }
+
+ int version;
+ in >> version >> d->clientPlugins;
+
+ // Send the hello answer immediately, since it needs to arrive before
+ // the plugins below start sending messages.
+ QByteArray helloAnswer;
+ {
+ QDataStream out(&helloAnswer, QIODevice::WriteOnly);
+ out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys();
+ }
+ d->connection->send(helloAnswer);
+
+ d->gotHello = true;
+
+ QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter) {
+ QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
+ if (d->clientPlugins.contains(iter.key()))
+ newStatus = QDeclarativeDebugService::Enabled;
+ iter.value()->d_func()->status = newStatus;
+ iter.value()->statusChanged(newStatus);
+ }
+
+ qDebug("QDeclarativeDebugServer: Connection established");
+ } else {
+
+ QString debugServer(QLatin1String("QDeclarativeDebugServer"));
+
+ QString name;
+ in >> name;
+
+ if (name == debugServer) {
+ int op = -1;
+ in >> op;
+
+ if (op == 1) {
+ // Service Discovery
+ QStringList oldClientPlugins = d->clientPlugins;
+ in >> d->clientPlugins;
+
+ QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter) {
+ const QString pluginName = iter.key();
+ QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
+ if (d->clientPlugins.contains(pluginName))
+ newStatus = QDeclarativeDebugService::Enabled;
+
+ if (oldClientPlugins.contains(pluginName)
+ != d->clientPlugins.contains(pluginName)) {
+ iter.value()->d_func()->status = newStatus;
+ iter.value()->statusChanged(newStatus);
+ }
+ }
+ } else {
+ qWarning("QDeclarativeDebugServer: Invalid control message %d", op);
+ }
+ } else {
+ QByteArray message;
+ in >> message;
+
+ if (d->waitingForMsgFromService == name) {
+ // deliver directly so that it is delivered before waitForMessage is returning.
+ d->_q_deliverMessage(name, message);
+ d->waitingForMsgSucceeded = true;
+ } else {
+ // deliver message in next event loop run.
+ // Fixes the case that the service does start it's own event loop ...,
+ // but the networking code doesn't deliver any new messages because readyRead
+ // hasn't returned.
+ QMetaObject::invokeMethod(this, "_q_deliverMessage", Qt::QueuedConnection,
+ Q_ARG(QString, name),
+ Q_ARG(QByteArray, message));
+ }
+ }
+ }
+}
+
+void QDeclarativeDebugServerPrivate::_q_deliverMessage(const QString &serviceName, const QByteArray &message)
+{
+ QHash<QString, QDeclarativeDebugService *>::Iterator iter = plugins.find(serviceName);
+ if (iter == plugins.end()) {
+ qWarning() << "QDeclarativeDebugServer: Message received for missing plugin" << serviceName;
+ } else {
+ (*iter)->messageReceived(message);
+ }
+}
+
+QList<QDeclarativeDebugService*> QDeclarativeDebugServer::services() const
+{
+ const Q_D(QDeclarativeDebugServer);
+ return d->plugins.values();
+}
+
+QStringList QDeclarativeDebugServer::serviceNames() const
+{
+ const Q_D(QDeclarativeDebugServer);
+ return d->plugins.keys();
+}
+
+bool QDeclarativeDebugServer::addService(QDeclarativeDebugService *service)
+{
+ Q_D(QDeclarativeDebugServer);
+ if (!service || d->plugins.contains(service->name()))
+ return false;
+
+ d->plugins.insert(service->name(), service);
+ d->advertisePlugins();
+
+ QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable;
+ if (d->clientPlugins.contains(service->name()))
+ newStatus = QDeclarativeDebugService::Enabled;
+ service->d_func()->status = newStatus;
+ service->statusChanged(newStatus);
+ return true;
+}
+
+bool QDeclarativeDebugServer::removeService(QDeclarativeDebugService *service)
+{
+ Q_D(QDeclarativeDebugServer);
+ if (!service || !d->plugins.contains(service->name()))
+ return false;
+
+ d->plugins.remove(service->name());
+ d->advertisePlugins();
+
+ QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::NotConnected;
+ service->d_func()->server = 0;
+ service->d_func()->status = newStatus;
+ service->statusChanged(newStatus);
+ return true;
+}
+
+void QDeclarativeDebugServer::sendMessage(QDeclarativeDebugService *service,
+ const QByteArray &message)
+{
+ Q_D(QDeclarativeDebugServer);
+ QByteArray msg;
+ {
+ QDataStream out(&msg, QIODevice::WriteOnly);
+ out << service->name() << message;
+ }
+ d->connection->send(msg);
+}
+
+bool QDeclarativeDebugServer::waitForMessage(QDeclarativeDebugService *service)
+{
+ Q_D(QDeclarativeDebugServer);
+
+ if (!service
+ || !d->plugins.contains(service->name())
+ || !d->waitingForMsgFromService.isEmpty())
+ return false;
+
+ d->waitingForMsgFromService = service->name();
+
+ do {
+ d->connection->waitForMessage();
+ } while (!d->waitingForMsgSucceeded);
+ d->waitingForMsgSucceeded = false;
+ d->waitingForMsgFromService.clear();
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qdeclarativedebugserver_p.cpp"
diff --git a/src/declarative/debugger/qdeclarativedebugserver_p.h b/src/declarative/debugger/qdeclarativedebugserver_p.h
new file mode 100644
index 00000000..922f981d
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebugserver_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEDEBUGSERVER_H
+#define QDECLARATIVEDEBUGSERVER_H
+
+#include <private/qdeclarativeglobal_p.h>
+#include <private/qdeclarativedebugserverconnection_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeDebugService;
+
+class QDeclarativeDebugServerPrivate;
+class Q_DECLARATIVE_EXPORT QDeclarativeDebugServer : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeDebugServer)
+ Q_DISABLE_COPY(QDeclarativeDebugServer)
+public:
+ static QDeclarativeDebugServer *instance();
+
+ void setConnection(QDeclarativeDebugServerConnection *connection);
+
+ bool hasDebuggingClient() const;
+
+ QList<QDeclarativeDebugService*> services() const;
+ QStringList serviceNames() const;
+
+ bool addService(QDeclarativeDebugService *service);
+ bool removeService(QDeclarativeDebugService *service);
+
+ void sendMessage(QDeclarativeDebugService *service, const QByteArray &message);
+ void receiveMessage(const QByteArray &message);
+
+ bool waitForMessage(QDeclarativeDebugService *service);
+
+private:
+ friend class QDeclarativeDebugService;
+ friend class QDeclarativeDebugServicePrivate;
+ QDeclarativeDebugServer();
+ Q_PRIVATE_SLOT(d_func(), void _q_deliverMessage(QString, QByteArray))
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEDEBUGSERVICE_H
diff --git a/src/declarative/debugger/qdeclarativedebugserverconnection_p.h b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h
new file mode 100644
index 00000000..16fa798e
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEDEBUGSERVERCONNECTION_H
+#define QDECLARATIVEDEBUGSERVERCONNECTION_H
+
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeDebugServer;
+class Q_DECLARATIVE_EXPORT QDeclarativeDebugServerConnection
+{
+public:
+ QDeclarativeDebugServerConnection() {}
+ virtual ~QDeclarativeDebugServerConnection() {}
+
+ virtual void setServer(QDeclarativeDebugServer *server) = 0;
+ virtual void setPort(int port, bool bock) = 0;
+ virtual bool isConnected() const = 0;
+ virtual void send(const QByteArray &message) = 0;
+ virtual void disconnect() = 0;
+ virtual bool waitForMessage() = 0;
+};
+
+Q_DECLARE_INTERFACE(QDeclarativeDebugServerConnection, "com.trolltech.Qt.QDeclarativeDebugServerConnection/1.0")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEDEBUGSERVERCONNECTION_H
diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp
new file mode 100644
index 00000000..111bd24c
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebugservice.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativedebugservice_p.h"
+#include "private/qdeclarativedebugservice_p_p.h"
+#include "private/qdeclarativedebugserver_p.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+QDeclarativeDebugServicePrivate::QDeclarativeDebugServicePrivate()
+: server(0)
+{
+}
+
+QDeclarativeDebugService::QDeclarativeDebugService(const QString &name, QObject *parent)
+: QObject(*(new QDeclarativeDebugServicePrivate), parent)
+{
+ Q_D(QDeclarativeDebugService);
+ d->name = name;
+ d->server = QDeclarativeDebugServer::instance();
+ d->status = QDeclarativeDebugService::NotConnected;
+
+ if (!d->server)
+ return;
+
+ if (d->server->serviceNames().contains(name)) {
+ qWarning() << "QDeclarativeDebugService: Conflicting plugin name" << name;
+ d->server = 0;
+ } else {
+ d->server->addService(this);
+ }
+}
+
+QDeclarativeDebugService::~QDeclarativeDebugService()
+{
+ Q_D(const QDeclarativeDebugService);
+ if (d->server) {
+ d->server->removeService(this);
+ }
+}
+
+QString QDeclarativeDebugService::name() const
+{
+ Q_D(const QDeclarativeDebugService);
+ return d->name;
+}
+
+QDeclarativeDebugService::Status QDeclarativeDebugService::status() const
+{
+ Q_D(const QDeclarativeDebugService);
+ return d->status;
+}
+
+namespace {
+
+ struct ObjectReference
+ {
+ QPointer<QObject> object;
+ int id;
+ };
+
+ struct ObjectReferenceHash
+ {
+ ObjectReferenceHash() : nextId(0) {}
+
+ QHash<QObject *, ObjectReference> objects;
+ QHash<int, QObject *> ids;
+
+ int nextId;
+ };
+
+}
+Q_GLOBAL_STATIC(ObjectReferenceHash, objectReferenceHash);
+
+
+/*!
+ Returns a unique id for \a object. Calling this method multiple times
+ for the same object will return the same id.
+*/
+int QDeclarativeDebugService::idForObject(QObject *object)
+{
+ if (!object)
+ return -1;
+
+ ObjectReferenceHash *hash = objectReferenceHash();
+ QHash<QObject *, ObjectReference>::Iterator iter =
+ hash->objects.find(object);
+
+ if (iter == hash->objects.end()) {
+ int id = hash->nextId++;
+
+ hash->ids.insert(id, object);
+ iter = hash->objects.insert(object, ObjectReference());
+ iter->object = object;
+ iter->id = id;
+ } else if (iter->object != object) {
+ int id = hash->nextId++;
+
+ hash->ids.remove(iter->id);
+
+ hash->ids.insert(id, object);
+ iter->object = object;
+ iter->id = id;
+ }
+ return iter->id;
+}
+
+/*!
+ Returns the object for unique \a id. If the object has not previously been
+ assigned an id, through idForObject(), then 0 is returned. If the object
+ has been destroyed, 0 is returned.
+*/
+QObject *QDeclarativeDebugService::objectForId(int id)
+{
+ ObjectReferenceHash *hash = objectReferenceHash();
+
+ QHash<int, QObject *>::Iterator iter = hash->ids.find(id);
+ if (iter == hash->ids.end())
+ return 0;
+
+
+ QHash<QObject *, ObjectReference>::Iterator objIter =
+ hash->objects.find(*iter);
+ Q_ASSERT(objIter != hash->objects.end());
+
+ if (objIter->object == 0) {
+ hash->ids.erase(iter);
+ hash->objects.erase(objIter);
+ return 0;
+ } else {
+ return *iter;
+ }
+}
+
+bool QDeclarativeDebugService::isDebuggingEnabled()
+{
+ return QDeclarativeDebugServer::instance() != 0;
+}
+
+bool QDeclarativeDebugService::hasDebuggingClient()
+{
+ return QDeclarativeDebugServer::instance() != 0
+ && QDeclarativeDebugServer::instance()->hasDebuggingClient();
+}
+
+QString QDeclarativeDebugService::objectToString(QObject *obj)
+{
+ if(!obj)
+ return QLatin1String("NULL");
+
+ QString objectName = obj->objectName();
+ if(objectName.isEmpty())
+ objectName = QLatin1String("<unnamed>");
+
+ QString rv = QString::fromUtf8(obj->metaObject()->className()) +
+ QLatin1String(": ") + objectName;
+
+ return rv;
+}
+
+void QDeclarativeDebugService::sendMessage(const QByteArray &message)
+{
+ Q_D(QDeclarativeDebugService);
+
+ if (status() != Enabled)
+ return;
+
+ d->server->sendMessage(this, message);
+}
+
+bool QDeclarativeDebugService::waitForMessage()
+{
+ Q_D(QDeclarativeDebugService);
+
+ if (status() != Enabled)
+ return false;
+
+ return d->server->waitForMessage(this);
+}
+
+void QDeclarativeDebugService::statusChanged(Status)
+{
+}
+
+void QDeclarativeDebugService::messageReceived(const QByteArray &)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativedebugservice_p.h b/src/declarative/debugger/qdeclarativedebugservice_p.h
new file mode 100644
index 00000000..2abef713
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebugservice_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEDEBUGSERVICE_H
+#define QDECLARATIVEDEBUGSERVICE_H
+
+#include <QtCore/qobject.h>
+
+#include <private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeDebugServicePrivate;
+class Q_DECLARATIVE_EXPORT QDeclarativeDebugService : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeDebugService)
+ Q_DISABLE_COPY(QDeclarativeDebugService)
+
+public:
+ explicit QDeclarativeDebugService(const QString &, QObject *parent = 0);
+ ~QDeclarativeDebugService();
+
+ QString name() const;
+
+ enum Status { NotConnected, Unavailable, Enabled };
+ Status status() const;
+
+ void sendMessage(const QByteArray &);
+ bool waitForMessage();
+
+ static int idForObject(QObject *);
+ static QObject *objectForId(int);
+
+ static QString objectToString(QObject *obj);
+
+ static bool isDebuggingEnabled();
+ static bool hasDebuggingClient();
+
+protected:
+ virtual void statusChanged(Status);
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ friend class QDeclarativeDebugServer;
+ friend class QDeclarativeDebugServerPrivate;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEDEBUGSERVICE_H
+
diff --git a/src/declarative/debugger/qdeclarativedebugservice_p_p.h b/src/declarative/debugger/qdeclarativedebugservice_p_p.h
new file mode 100644
index 00000000..1a169334
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebugservice_p_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEDEBUGSERVICE_P_H
+#define QDECLARATIVEDEBUGSERVICE_P_H
+
+#include <QtCore/qglobal.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeDebugServer;
+
+class QDeclarativeDebugServicePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarativeDebugService)
+public:
+ QDeclarativeDebugServicePrivate();
+
+ QString name;
+ QDeclarativeDebugServer *server;
+ QDeclarativeDebugService::Status status;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEDEBUGSERVICE_P_H
diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp
new file mode 100644
index 00000000..16e6dfb1
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 "qdeclarativedebugtrace_p.h"
+
+#include <QtCore/qdatastream.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qtimer.h>
+
+Q_GLOBAL_STATIC(QDeclarativeDebugTrace, traceInstance);
+
+// convert to a QByteArray that can be sent to the debug client
+// use of QDataStream can skew results if m_deferredSend == false
+// (see tst_qperformancetimer::trace() benchmark)
+QByteArray QDeclarativeDebugData::toByteArray() const
+{
+ QByteArray data;
+ //### using QDataStream is relatively expensive
+ QDataStream ds(&data, QIODevice::WriteOnly);
+ ds << time << messageType << detailType;
+ if (messageType == (int)QDeclarativeDebugTrace::RangeData)
+ ds << detailData;
+ if (messageType == (int)QDeclarativeDebugTrace::RangeLocation)
+ ds << detailData << line;
+ return data;
+}
+
+QDeclarativeDebugTrace::QDeclarativeDebugTrace()
+: QDeclarativeDebugService(QLatin1String("CanvasFrameRate")),
+ m_enabled(false), m_deferredSend(true), m_messageReceived(false)
+{
+ m_timer.start();
+ if (status() == Enabled) {
+ // wait for first message indicating whether to trace or not
+ while (!m_messageReceived)
+ waitForMessage();
+ }
+}
+
+void QDeclarativeDebugTrace::addEvent(EventType t)
+{
+ if (QDeclarativeDebugService::isDebuggingEnabled())
+ traceInstance()->addEventImpl(t);
+}
+
+void QDeclarativeDebugTrace::startRange(RangeType t)
+{
+ if (QDeclarativeDebugService::isDebuggingEnabled())
+ traceInstance()->startRangeImpl(t);
+}
+
+void QDeclarativeDebugTrace::rangeData(RangeType t, const QString &data)
+{
+ if (QDeclarativeDebugService::isDebuggingEnabled())
+ traceInstance()->rangeDataImpl(t, data);
+}
+
+void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &data)
+{
+ if (QDeclarativeDebugService::isDebuggingEnabled())
+ traceInstance()->rangeDataImpl(t, data);
+}
+
+void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QString &fileName, int line)
+{
+ if (QDeclarativeDebugService::isDebuggingEnabled())
+ traceInstance()->rangeLocationImpl(t, fileName, line);
+}
+
+void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QUrl &fileName, int line)
+{
+ if (QDeclarativeDebugService::isDebuggingEnabled())
+ traceInstance()->rangeLocationImpl(t, fileName, line);
+}
+
+void QDeclarativeDebugTrace::endRange(RangeType t)
+{
+ if (QDeclarativeDebugService::isDebuggingEnabled())
+ traceInstance()->endRangeImpl(t);
+}
+
+void QDeclarativeDebugTrace::addEventImpl(EventType event)
+{
+ if (status() != Enabled || !m_enabled)
+ return;
+
+ QDeclarativeDebugData ed = {m_timer.elapsed(), (int)Event, (int)event, QString(), -1};
+ processMessage(ed);
+}
+
+void QDeclarativeDebugTrace::startRangeImpl(RangeType range)
+{
+ if (status() != Enabled || !m_enabled)
+ return;
+
+ QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeStart, (int)range, QString(), -1};
+ processMessage(rd);
+}
+
+void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData)
+{
+ if (status() != Enabled || !m_enabled)
+ return;
+
+ QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData, -1};
+ processMessage(rd);
+}
+
+void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData)
+{
+ if (status() != Enabled || !m_enabled)
+ return;
+
+ QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1};
+ processMessage(rd);
+}
+
+void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QString &fileName, int line)
+{
+ if (status() != Enabled || !m_enabled)
+ return;
+
+ QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeLocation, (int)range, fileName, line};
+ processMessage(rd);
+}
+
+void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QUrl &fileName, int line)
+{
+ if (status() != Enabled || !m_enabled)
+ return;
+
+ QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line};
+ processMessage(rd);
+}
+
+void QDeclarativeDebugTrace::endRangeImpl(RangeType range)
+{
+ if (status() != Enabled || !m_enabled)
+ return;
+
+ QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeEnd, (int)range, QString(), -1};
+ processMessage(rd);
+}
+
+/*
+ Either send the message directly, or queue up
+ a list of messages to send later (via sendMessages)
+*/
+void QDeclarativeDebugTrace::processMessage(const QDeclarativeDebugData &message)
+{
+ if (m_deferredSend)
+ m_data.append(message);
+ else
+ sendMessage(message.toByteArray());
+}
+
+/*
+ Send the messages queued up by processMessage
+*/
+void QDeclarativeDebugTrace::sendMessages()
+{
+ if (m_deferredSend) {
+ //### this is a suboptimal way to send batched messages
+ for (int i = 0; i < m_data.count(); ++i)
+ sendMessage(m_data.at(i).toByteArray());
+ m_data.clear();
+
+ //indicate completion
+ QByteArray data;
+ QDataStream ds(&data, QIODevice::WriteOnly);
+ ds << (qint64)-1 << (int)Complete;
+ sendMessage(data);
+ }
+}
+
+void QDeclarativeDebugTrace::messageReceived(const QByteArray &message)
+{
+ QByteArray rwData = message;
+ QDataStream stream(&rwData, QIODevice::ReadOnly);
+
+ stream >> m_enabled;
+
+ m_messageReceived = true;
+
+ if (!m_enabled)
+ sendMessages();
+}
diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h
new file mode 100644
index 00000000..3cd73b07
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEDEBUGTRACE_P_H
+#define QDECLARATIVEDEBUGTRACE_P_H
+
+#include <private/qdeclarativedebugservice_p.h>
+#include <private/qperformancetimer_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+struct QDeclarativeDebugData
+{
+ qint64 time;
+ int messageType;
+ int detailType;
+
+ //###
+ QString detailData; //used by RangeData and RangeLocation
+ int line; //used by RangeLocation
+
+ QByteArray toByteArray() const;
+};
+
+class QUrl;
+class Q_AUTOTEST_EXPORT QDeclarativeDebugTrace : public QDeclarativeDebugService
+{
+public:
+ enum Message {
+ Event,
+ RangeStart,
+ RangeData,
+ RangeLocation,
+ RangeEnd,
+ Complete,
+
+ MaximumMessage
+ };
+
+ enum EventType {
+ FramePaint,
+ Mouse,
+ Key,
+
+ MaximumEventType
+ };
+
+ enum RangeType {
+ Painting,
+ Compiling,
+ Creating,
+ Binding, //running a binding
+ HandlingSignal, //running a signal handler
+
+ MaximumRangeType
+ };
+
+ static void addEvent(EventType);
+
+ static void startRange(RangeType);
+ static void rangeData(RangeType, const QString &);
+ static void rangeData(RangeType, const QUrl &);
+ static void rangeLocation(RangeType, const QString &, int);
+ static void rangeLocation(RangeType, const QUrl &, int);
+ static void endRange(RangeType);
+
+ QDeclarativeDebugTrace();
+protected:
+ virtual void messageReceived(const QByteArray &);
+private:
+ void addEventImpl(EventType);
+ void startRangeImpl(RangeType);
+ void rangeDataImpl(RangeType, const QString &);
+ void rangeDataImpl(RangeType, const QUrl &);
+ void rangeLocationImpl(RangeType, const QString &, int);
+ void rangeLocationImpl(RangeType, const QUrl &, int);
+ void endRangeImpl(RangeType);
+ void processMessage(const QDeclarativeDebugData &);
+ void sendMessages();
+ QPerformanceTimer m_timer;
+ bool m_enabled;
+ bool m_deferredSend;
+ bool m_messageReceived;
+ QList<QDeclarativeDebugData> m_data;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEDEBUGTRACE_P_H
+
diff --git a/src/declarative/debugger/qdeclarativeenginedebug.cpp b/src/declarative/debugger/qdeclarativeenginedebug.cpp
new file mode 100644
index 00000000..74316574
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeenginedebug.cpp
@@ -0,0 +1,1068 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativeenginedebug_p.h"
+
+#include "private/qdeclarativedebugclient_p.h"
+
+#include <qdeclarativeenginedebugservice_p.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeEngineDebugClient : public QDeclarativeDebugClient
+{
+public:
+ QDeclarativeEngineDebugClient(QDeclarativeDebugConnection *client, QDeclarativeEngineDebugPrivate *p);
+
+protected:
+ virtual void statusChanged(Status status);
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ QDeclarativeEngineDebugPrivate *priv;
+ friend class QDeclarativeEngineDebugPrivate;
+};
+
+class QDeclarativeEngineDebugPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarativeEngineDebug)
+public:
+ QDeclarativeEngineDebugPrivate(QDeclarativeDebugConnection *);
+ ~QDeclarativeEngineDebugPrivate();
+
+ void statusChanged(QDeclarativeEngineDebug::Status status);
+ void message(const QByteArray &);
+
+ QDeclarativeEngineDebugClient *client;
+ int nextId;
+ int getId();
+
+ void decode(QDataStream &, QDeclarativeDebugContextReference &);
+ void decode(QDataStream &, QDeclarativeDebugObjectReference &, bool simple);
+
+ static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugEnginesQuery *);
+ static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugRootContextQuery *);
+ static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugObjectQuery *);
+ static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugExpressionQuery *);
+ static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugWatch *);
+
+ QHash<int, QDeclarativeDebugEnginesQuery *> enginesQuery;
+ QHash<int, QDeclarativeDebugRootContextQuery *> rootContextQuery;
+ QHash<int, QDeclarativeDebugObjectQuery *> objectQuery;
+ QHash<int, QDeclarativeDebugExpressionQuery *> expressionQuery;
+
+ QHash<int, QDeclarativeDebugWatch *> watched;
+};
+
+QDeclarativeEngineDebugClient::QDeclarativeEngineDebugClient(QDeclarativeDebugConnection *client,
+ QDeclarativeEngineDebugPrivate *p)
+: QDeclarativeDebugClient(QLatin1String("QDeclarativeEngine"), client), priv(p)
+{
+}
+
+void QDeclarativeEngineDebugClient::statusChanged(Status status)
+{
+ if (priv)
+ priv->statusChanged(static_cast<QDeclarativeEngineDebug::Status>(status));
+}
+
+void QDeclarativeEngineDebugClient::messageReceived(const QByteArray &data)
+{
+ if (priv)
+ priv->message(data);
+}
+
+QDeclarativeEngineDebugPrivate::QDeclarativeEngineDebugPrivate(QDeclarativeDebugConnection *c)
+: client(new QDeclarativeEngineDebugClient(c, this)), nextId(0)
+{
+}
+
+QDeclarativeEngineDebugPrivate::~QDeclarativeEngineDebugPrivate()
+{
+ if (client)
+ client->priv = 0;
+ delete client;
+
+ QHash<int, QDeclarativeDebugEnginesQuery*>::iterator enginesIter = enginesQuery.begin();
+ for (; enginesIter != enginesQuery.end(); ++enginesIter) {
+ enginesIter.value()->m_client = 0;
+ if (enginesIter.value()->state() == QDeclarativeDebugQuery::Waiting)
+ enginesIter.value()->setState(QDeclarativeDebugQuery::Error);
+ }
+
+ QHash<int, QDeclarativeDebugRootContextQuery*>::iterator rootContextIter = rootContextQuery.begin();
+ for (; rootContextIter != rootContextQuery.end(); ++rootContextIter) {
+ rootContextIter.value()->m_client = 0;
+ if (rootContextIter.value()->state() == QDeclarativeDebugQuery::Waiting)
+ rootContextIter.value()->setState(QDeclarativeDebugQuery::Error);
+ }
+
+ QHash<int, QDeclarativeDebugObjectQuery*>::iterator objectIter = objectQuery.begin();
+ for (; objectIter != objectQuery.end(); ++objectIter) {
+ objectIter.value()->m_client = 0;
+ if (objectIter.value()->state() == QDeclarativeDebugQuery::Waiting)
+ objectIter.value()->setState(QDeclarativeDebugQuery::Error);
+ }
+
+ QHash<int, QDeclarativeDebugExpressionQuery*>::iterator exprIter = expressionQuery.begin();
+ for (; exprIter != expressionQuery.end(); ++exprIter) {
+ exprIter.value()->m_client = 0;
+ if (exprIter.value()->state() == QDeclarativeDebugQuery::Waiting)
+ exprIter.value()->setState(QDeclarativeDebugQuery::Error);
+ }
+
+ QHash<int, QDeclarativeDebugWatch*>::iterator watchIter = watched.begin();
+ for (; watchIter != watched.end(); ++watchIter) {
+ watchIter.value()->m_client = 0;
+ watchIter.value()->setState(QDeclarativeDebugWatch::Dead);
+ }
+}
+
+int QDeclarativeEngineDebugPrivate::getId()
+{
+ return nextId++;
+}
+
+void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, QDeclarativeDebugEnginesQuery *q)
+{
+ if (c && q) {
+ QDeclarativeEngineDebugPrivate *p = (QDeclarativeEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->enginesQuery.remove(q->m_queryId);
+ }
+}
+
+void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c,
+ QDeclarativeDebugRootContextQuery *q)
+{
+ if (c && q) {
+ QDeclarativeEngineDebugPrivate *p = (QDeclarativeEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->rootContextQuery.remove(q->m_queryId);
+ }
+}
+
+void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, QDeclarativeDebugObjectQuery *q)
+{
+ if (c && q) {
+ QDeclarativeEngineDebugPrivate *p = (QDeclarativeEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->objectQuery.remove(q->m_queryId);
+ }
+}
+
+void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, QDeclarativeDebugExpressionQuery *q)
+{
+ if (c && q) {
+ QDeclarativeEngineDebugPrivate *p = (QDeclarativeEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->expressionQuery.remove(q->m_queryId);
+ }
+}
+
+void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, QDeclarativeDebugWatch *w)
+{
+ if (c && w) {
+ QDeclarativeEngineDebugPrivate *p = (QDeclarativeEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->watched.remove(w->m_queryId);
+ }
+}
+
+void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugObjectReference &o,
+ bool simple)
+{
+ QDeclarativeEngineDebugService::QDeclarativeObjectData data;
+ ds >> data;
+ o.m_debugId = data.objectId;
+ o.m_class = data.objectType;
+ o.m_idString = data.idString;
+ o.m_name = data.objectName;
+ o.m_source.m_url = data.url;
+ o.m_source.m_lineNumber = data.lineNumber;
+ o.m_source.m_columnNumber = data.columnNumber;
+ o.m_contextDebugId = data.contextId;
+
+ if (simple)
+ return;
+
+ int childCount;
+ bool recur;
+ ds >> childCount >> recur;
+
+ for (int ii = 0; ii < childCount; ++ii) {
+ o.m_children.append(QDeclarativeDebugObjectReference());
+ decode(ds, o.m_children.last(), !recur);
+ }
+
+ int propCount;
+ ds >> propCount;
+
+ for (int ii = 0; ii < propCount; ++ii) {
+ QDeclarativeEngineDebugService::QDeclarativeObjectProperty data;
+ ds >> data;
+ QDeclarativeDebugPropertyReference prop;
+ prop.m_objectDebugId = o.m_debugId;
+ prop.m_name = data.name;
+ prop.m_binding = data.binding;
+ prop.m_hasNotifySignal = data.hasNotifySignal;
+ prop.m_valueTypeName = data.valueTypeName;
+ switch (data.type) {
+ case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::Basic:
+ case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::List:
+ case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::SignalProperty:
+ {
+ prop.m_value = data.value;
+ break;
+ }
+ case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::Object:
+ {
+ QDeclarativeDebugObjectReference obj;
+ obj.m_debugId = prop.m_value.toInt();
+ prop.m_value = QVariant::fromValue(obj);
+ break;
+ }
+ case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::Unknown:
+ break;
+ }
+ o.m_properties << prop;
+ }
+}
+
+void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugContextReference &c)
+{
+ ds >> c.m_name >> c.m_debugId;
+
+ int contextCount;
+ ds >> contextCount;
+
+ for (int ii = 0; ii < contextCount; ++ii) {
+ c.m_contexts.append(QDeclarativeDebugContextReference());
+ decode(ds, c.m_contexts.last());
+ }
+
+ int objectCount;
+ ds >> objectCount;
+
+ for (int ii = 0; ii < objectCount; ++ii) {
+ QDeclarativeDebugObjectReference obj;
+ decode(ds, obj, true);
+
+ obj.m_contextDebugId = c.m_debugId;
+ c.m_objects << obj;
+ }
+}
+
+void QDeclarativeEngineDebugPrivate::statusChanged(QDeclarativeEngineDebug::Status status)
+{
+ emit q_func()->statusChanged(status);
+}
+
+void QDeclarativeEngineDebugPrivate::message(const QByteArray &data)
+{
+ QDataStream ds(data);
+
+ QByteArray type;
+ ds >> type;
+
+ //qDebug() << "QDeclarativeEngineDebugPrivate::message()" << type;
+
+ if (type == "LIST_ENGINES_R") {
+ int queryId;
+ ds >> queryId;
+
+ QDeclarativeDebugEnginesQuery *query = enginesQuery.value(queryId);
+ if (!query)
+ return;
+ enginesQuery.remove(queryId);
+
+ int count;
+ ds >> count;
+
+ for (int ii = 0; ii < count; ++ii) {
+ QDeclarativeDebugEngineReference ref;
+ ds >> ref.m_name;
+ ds >> ref.m_debugId;
+ query->m_engines << ref;
+ }
+
+ query->m_client = 0;
+ query->setState(QDeclarativeDebugQuery::Completed);
+ } else if (type == "LIST_OBJECTS_R") {
+ int queryId;
+ ds >> queryId;
+
+ QDeclarativeDebugRootContextQuery *query = rootContextQuery.value(queryId);
+ if (!query)
+ return;
+ rootContextQuery.remove(queryId);
+
+ if (!ds.atEnd())
+ decode(ds, query->m_context);
+
+ query->m_client = 0;
+ query->setState(QDeclarativeDebugQuery::Completed);
+ } else if (type == "FETCH_OBJECT_R") {
+ int queryId;
+ ds >> queryId;
+
+ QDeclarativeDebugObjectQuery *query = objectQuery.value(queryId);
+ if (!query)
+ return;
+ objectQuery.remove(queryId);
+
+ if (!ds.atEnd())
+ decode(ds, query->m_object, false);
+
+ query->m_client = 0;
+ query->setState(QDeclarativeDebugQuery::Completed);
+ } else if (type == "EVAL_EXPRESSION_R") {
+ int queryId;
+ QVariant result;
+ ds >> queryId >> result;
+
+ QDeclarativeDebugExpressionQuery *query = expressionQuery.value(queryId);
+ if (!query)
+ return;
+ expressionQuery.remove(queryId);
+
+ query->m_result = result;
+ query->m_client = 0;
+ query->setState(QDeclarativeDebugQuery::Completed);
+ } else if (type == "WATCH_PROPERTY_R") {
+ int queryId;
+ bool ok;
+ ds >> queryId >> ok;
+
+ QDeclarativeDebugWatch *watch = watched.value(queryId);
+ if (!watch)
+ return;
+
+ watch->setState(ok ? QDeclarativeDebugWatch::Active : QDeclarativeDebugWatch::Inactive);
+ } else if (type == "WATCH_OBJECT_R") {
+ int queryId;
+ bool ok;
+ ds >> queryId >> ok;
+
+ QDeclarativeDebugWatch *watch = watched.value(queryId);
+ if (!watch)
+ return;
+
+ watch->setState(ok ? QDeclarativeDebugWatch::Active : QDeclarativeDebugWatch::Inactive);
+ } else if (type == "WATCH_EXPR_OBJECT_R") {
+ int queryId;
+ bool ok;
+ ds >> queryId >> ok;
+
+ QDeclarativeDebugWatch *watch = watched.value(queryId);
+ if (!watch)
+ return;
+
+ watch->setState(ok ? QDeclarativeDebugWatch::Active : QDeclarativeDebugWatch::Inactive);
+ } else if (type == "UPDATE_WATCH") {
+ int queryId;
+ int debugId;
+ QByteArray name;
+ QVariant value;
+ ds >> queryId >> debugId >> name >> value;
+
+ QDeclarativeDebugWatch *watch = watched.value(queryId, 0);
+ if (!watch)
+ return;
+ emit watch->valueChanged(name, value);
+ } else if (type == "OBJECT_CREATED") {
+ emit q_func()->newObjects();
+ }
+}
+
+QDeclarativeEngineDebug::QDeclarativeEngineDebug(QDeclarativeDebugConnection *client, QObject *parent)
+: QObject(*(new QDeclarativeEngineDebugPrivate(client)), parent)
+{
+}
+
+QDeclarativeEngineDebug::Status QDeclarativeEngineDebug::status() const
+{
+ Q_D(const QDeclarativeEngineDebug);
+
+ return static_cast<QDeclarativeEngineDebug::Status>(d->client->status());
+}
+
+QDeclarativeDebugPropertyWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugPropertyReference &property, QObject *parent)
+{
+ Q_D(QDeclarativeEngineDebug);
+
+ QDeclarativeDebugPropertyWatch *watch = new QDeclarativeDebugPropertyWatch(parent);
+ if (d->client->status() == QDeclarativeDebugClient::Enabled) {
+ int queryId = d->getId();
+ watch->m_queryId = queryId;
+ watch->m_client = this;
+ watch->m_objectDebugId = property.objectDebugId();
+ watch->m_name = property.name();
+ d->watched.insert(queryId, watch);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("WATCH_PROPERTY") << queryId << property.objectDebugId() << property.name().toUtf8();
+ d->client->sendMessage(message);
+ } else {
+ watch->m_state = QDeclarativeDebugWatch::Dead;
+ }
+
+ return watch;
+}
+
+QDeclarativeDebugWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugContextReference &, const QString &, QObject *)
+{
+ qWarning("QDeclarativeEngineDebug::addWatch(): Not implemented");
+ return 0;
+}
+
+QDeclarativeDebugObjectExpressionWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugObjectReference &object, const QString &expr, QObject *parent)
+{
+ Q_D(QDeclarativeEngineDebug);
+ QDeclarativeDebugObjectExpressionWatch *watch = new QDeclarativeDebugObjectExpressionWatch(parent);
+ if (d->client->status() == QDeclarativeDebugClient::Enabled) {
+ int queryId = d->getId();
+ watch->m_queryId = queryId;
+ watch->m_client = this;
+ watch->m_objectDebugId = object.debugId();
+ watch->m_expr = expr;
+ d->watched.insert(queryId, watch);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("WATCH_EXPR_OBJECT") << queryId << object.debugId() << expr;
+ d->client->sendMessage(message);
+ } else {
+ watch->m_state = QDeclarativeDebugWatch::Dead;
+ }
+ return watch;
+}
+
+QDeclarativeDebugWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugObjectReference &object, QObject *parent)
+{
+ Q_D(QDeclarativeEngineDebug);
+
+ QDeclarativeDebugWatch *watch = new QDeclarativeDebugWatch(parent);
+ if (d->client->status() == QDeclarativeDebugClient::Enabled) {
+ int queryId = d->getId();
+ watch->m_queryId = queryId;
+ watch->m_client = this;
+ watch->m_objectDebugId = object.debugId();
+ d->watched.insert(queryId, watch);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("WATCH_OBJECT") << queryId << object.debugId();
+ d->client->sendMessage(message);
+ } else {
+ watch->m_state = QDeclarativeDebugWatch::Dead;
+ }
+
+ return watch;
+}
+
+QDeclarativeDebugWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugFileReference &, QObject *)
+{
+ qWarning("QDeclarativeEngineDebug::addWatch(): Not implemented");
+ return 0;
+}
+
+void QDeclarativeEngineDebug::removeWatch(QDeclarativeDebugWatch *watch)
+{
+ Q_D(QDeclarativeEngineDebug);
+
+ if (!watch || !watch->m_client)
+ return;
+
+ watch->m_client = 0;
+ watch->setState(QDeclarativeDebugWatch::Inactive);
+
+ d->watched.remove(watch->queryId());
+
+ if (d->client && d->client->status() == QDeclarativeDebugClient::Enabled) {
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("NO_WATCH") << watch->queryId();
+ d->client->sendMessage(message);
+ }
+}
+
+QDeclarativeDebugEnginesQuery *QDeclarativeEngineDebug::queryAvailableEngines(QObject *parent)
+{
+ Q_D(QDeclarativeEngineDebug);
+
+ QDeclarativeDebugEnginesQuery *query = new QDeclarativeDebugEnginesQuery(parent);
+ if (d->client->status() == QDeclarativeDebugClient::Enabled) {
+ query->m_client = this;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->enginesQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("LIST_ENGINES") << queryId;
+ d->client->sendMessage(message);
+ } else {
+ query->m_state = QDeclarativeDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QDeclarativeDebugRootContextQuery *QDeclarativeEngineDebug::queryRootContexts(const QDeclarativeDebugEngineReference &engine, QObject *parent)
+{
+ Q_D(QDeclarativeEngineDebug);
+
+ QDeclarativeDebugRootContextQuery *query = new QDeclarativeDebugRootContextQuery(parent);
+ if (d->client->status() == QDeclarativeDebugClient::Enabled && engine.debugId() != -1) {
+ query->m_client = this;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->rootContextQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("LIST_OBJECTS") << queryId << engine.debugId();
+ d->client->sendMessage(message);
+ } else {
+ query->m_state = QDeclarativeDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QDeclarativeDebugObjectQuery *QDeclarativeEngineDebug::queryObject(const QDeclarativeDebugObjectReference &object, QObject *parent)
+{
+ Q_D(QDeclarativeEngineDebug);
+
+ QDeclarativeDebugObjectQuery *query = new QDeclarativeDebugObjectQuery(parent);
+ if (d->client->status() == QDeclarativeDebugClient::Enabled && object.debugId() != -1) {
+ query->m_client = this;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->objectQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId()
+ << false << true;
+ d->client->sendMessage(message);
+ } else {
+ query->m_state = QDeclarativeDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QDeclarativeDebugObjectQuery *QDeclarativeEngineDebug::queryObjectRecursive(const QDeclarativeDebugObjectReference &object, QObject *parent)
+{
+ Q_D(QDeclarativeEngineDebug);
+
+ QDeclarativeDebugObjectQuery *query = new QDeclarativeDebugObjectQuery(parent);
+ if (d->client->status() == QDeclarativeDebugClient::Enabled && object.debugId() != -1) {
+ query->m_client = this;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->objectQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId()
+ << true << true;
+ d->client->sendMessage(message);
+ } else {
+ query->m_state = QDeclarativeDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QDeclarativeDebugExpressionQuery *QDeclarativeEngineDebug::queryExpressionResult(int objectDebugId, const QString &expr, QObject *parent)
+{
+ Q_D(QDeclarativeEngineDebug);
+
+ QDeclarativeDebugExpressionQuery *query = new QDeclarativeDebugExpressionQuery(parent);
+ if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) {
+ query->m_client = this;
+ query->m_expr = expr;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->expressionQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("EVAL_EXPRESSION") << queryId << objectDebugId << expr;
+ d->client->sendMessage(message);
+ } else {
+ query->m_state = QDeclarativeDebugQuery::Error;
+ }
+
+ return query;
+}
+
+bool QDeclarativeEngineDebug::setBindingForObject(int objectDebugId, const QString &propertyName,
+ const QVariant &bindingExpression,
+ bool isLiteralValue,
+ QString source, int line)
+{
+ Q_D(QDeclarativeEngineDebug);
+
+ if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) {
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("SET_BINDING") << objectDebugId << propertyName << bindingExpression << isLiteralValue << source << line;
+ d->client->sendMessage(message);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QDeclarativeEngineDebug::resetBindingForObject(int objectDebugId, const QString &propertyName)
+{
+ Q_D(QDeclarativeEngineDebug);
+
+ if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) {
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("RESET_BINDING") << objectDebugId << propertyName;
+ d->client->sendMessage(message);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QDeclarativeEngineDebug::setMethodBody(int objectDebugId, const QString &methodName,
+ const QString &methodBody)
+{
+ Q_D(QDeclarativeEngineDebug);
+
+ if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) {
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("SET_METHOD_BODY") << objectDebugId << methodName << methodBody;
+ d->client->sendMessage(message);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+QDeclarativeDebugWatch::QDeclarativeDebugWatch(QObject *parent)
+: QObject(parent), m_state(Waiting), m_queryId(-1), m_client(0), m_objectDebugId(-1)
+{
+}
+
+QDeclarativeDebugWatch::~QDeclarativeDebugWatch()
+{
+ if (m_client && m_queryId != -1)
+ QDeclarativeEngineDebugPrivate::remove(m_client, this);
+}
+
+int QDeclarativeDebugWatch::queryId() const
+{
+ return m_queryId;
+}
+
+int QDeclarativeDebugWatch::objectDebugId() const
+{
+ return m_objectDebugId;
+}
+
+QDeclarativeDebugWatch::State QDeclarativeDebugWatch::state() const
+{
+ return m_state;
+}
+
+void QDeclarativeDebugWatch::setState(State s)
+{
+ if (m_state == s)
+ return;
+ m_state = s;
+ emit stateChanged(m_state);
+}
+
+QDeclarativeDebugPropertyWatch::QDeclarativeDebugPropertyWatch(QObject *parent)
+ : QDeclarativeDebugWatch(parent)
+{
+}
+
+QString QDeclarativeDebugPropertyWatch::name() const
+{
+ return m_name;
+}
+
+
+QDeclarativeDebugObjectExpressionWatch::QDeclarativeDebugObjectExpressionWatch(QObject *parent)
+ : QDeclarativeDebugWatch(parent)
+{
+}
+
+QString QDeclarativeDebugObjectExpressionWatch::expression() const
+{
+ return m_expr;
+}
+
+
+QDeclarativeDebugQuery::QDeclarativeDebugQuery(QObject *parent)
+: QObject(parent), m_state(Waiting)
+{
+}
+
+QDeclarativeDebugQuery::State QDeclarativeDebugQuery::state() const
+{
+ return m_state;
+}
+
+bool QDeclarativeDebugQuery::isWaiting() const
+{
+ return m_state == Waiting;
+}
+
+void QDeclarativeDebugQuery::setState(State s)
+{
+ if (m_state == s)
+ return;
+ m_state = s;
+ emit stateChanged(m_state);
+}
+
+QDeclarativeDebugEnginesQuery::QDeclarativeDebugEnginesQuery(QObject *parent)
+: QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1)
+{
+}
+
+QDeclarativeDebugEnginesQuery::~QDeclarativeDebugEnginesQuery()
+{
+ if (m_client && m_queryId != -1)
+ QDeclarativeEngineDebugPrivate::remove(m_client, this);
+}
+
+QList<QDeclarativeDebugEngineReference> QDeclarativeDebugEnginesQuery::engines() const
+{
+ return m_engines;
+}
+
+QDeclarativeDebugRootContextQuery::QDeclarativeDebugRootContextQuery(QObject *parent)
+: QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1)
+{
+}
+
+QDeclarativeDebugRootContextQuery::~QDeclarativeDebugRootContextQuery()
+{
+ if (m_client && m_queryId != -1)
+ QDeclarativeEngineDebugPrivate::remove(m_client, this);
+}
+
+QDeclarativeDebugContextReference QDeclarativeDebugRootContextQuery::rootContext() const
+{
+ return m_context;
+}
+
+QDeclarativeDebugObjectQuery::QDeclarativeDebugObjectQuery(QObject *parent)
+: QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1)
+{
+}
+
+QDeclarativeDebugObjectQuery::~QDeclarativeDebugObjectQuery()
+{
+ if (m_client && m_queryId != -1)
+ QDeclarativeEngineDebugPrivate::remove(m_client, this);
+}
+
+QDeclarativeDebugObjectReference QDeclarativeDebugObjectQuery::object() const
+{
+ return m_object;
+}
+
+QDeclarativeDebugExpressionQuery::QDeclarativeDebugExpressionQuery(QObject *parent)
+: QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1)
+{
+}
+
+QDeclarativeDebugExpressionQuery::~QDeclarativeDebugExpressionQuery()
+{
+ if (m_client && m_queryId != -1)
+ QDeclarativeEngineDebugPrivate::remove(m_client, this);
+}
+
+QVariant QDeclarativeDebugExpressionQuery::expression() const
+{
+ return m_expr;
+}
+
+QVariant QDeclarativeDebugExpressionQuery::result() const
+{
+ return m_result;
+}
+
+QDeclarativeDebugEngineReference::QDeclarativeDebugEngineReference()
+: m_debugId(-1)
+{
+}
+
+QDeclarativeDebugEngineReference::QDeclarativeDebugEngineReference(int debugId)
+: m_debugId(debugId)
+{
+}
+
+QDeclarativeDebugEngineReference::QDeclarativeDebugEngineReference(const QDeclarativeDebugEngineReference &o)
+: m_debugId(o.m_debugId), m_name(o.m_name)
+{
+}
+
+QDeclarativeDebugEngineReference &
+QDeclarativeDebugEngineReference::operator=(const QDeclarativeDebugEngineReference &o)
+{
+ m_debugId = o.m_debugId; m_name = o.m_name;
+ return *this;
+}
+
+int QDeclarativeDebugEngineReference::debugId() const
+{
+ return m_debugId;
+}
+
+QString QDeclarativeDebugEngineReference::name() const
+{
+ return m_name;
+}
+
+QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference()
+: m_debugId(-1), m_contextDebugId(-1)
+{
+}
+
+QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference(int debugId)
+: m_debugId(debugId), m_contextDebugId(-1)
+{
+}
+
+QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference(const QDeclarativeDebugObjectReference &o)
+: m_debugId(o.m_debugId), m_class(o.m_class), m_idString(o.m_idString),
+ m_name(o.m_name), m_source(o.m_source), m_contextDebugId(o.m_contextDebugId),
+ m_properties(o.m_properties), m_children(o.m_children)
+{
+}
+
+QDeclarativeDebugObjectReference &
+QDeclarativeDebugObjectReference::operator=(const QDeclarativeDebugObjectReference &o)
+{
+ m_debugId = o.m_debugId; m_class = o.m_class; m_idString = o.m_idString;
+ m_name = o.m_name; m_source = o.m_source; m_contextDebugId = o.m_contextDebugId;
+ m_properties = o.m_properties; m_children = o.m_children;
+ return *this;
+}
+
+int QDeclarativeDebugObjectReference::debugId() const
+{
+ return m_debugId;
+}
+
+QString QDeclarativeDebugObjectReference::className() const
+{
+ return m_class;
+}
+
+QString QDeclarativeDebugObjectReference::idString() const
+{
+ return m_idString;
+}
+
+QString QDeclarativeDebugObjectReference::name() const
+{
+ return m_name;
+}
+
+QDeclarativeDebugFileReference QDeclarativeDebugObjectReference::source() const
+{
+ return m_source;
+}
+
+int QDeclarativeDebugObjectReference::contextDebugId() const
+{
+ return m_contextDebugId;
+}
+
+QList<QDeclarativeDebugPropertyReference> QDeclarativeDebugObjectReference::properties() const
+{
+ return m_properties;
+}
+
+QList<QDeclarativeDebugObjectReference> QDeclarativeDebugObjectReference::children() const
+{
+ return m_children;
+}
+
+QDeclarativeDebugContextReference::QDeclarativeDebugContextReference()
+: m_debugId(-1)
+{
+}
+
+QDeclarativeDebugContextReference::QDeclarativeDebugContextReference(const QDeclarativeDebugContextReference &o)
+: m_debugId(o.m_debugId), m_name(o.m_name), m_objects(o.m_objects), m_contexts(o.m_contexts)
+{
+}
+
+QDeclarativeDebugContextReference &QDeclarativeDebugContextReference::operator=(const QDeclarativeDebugContextReference &o)
+{
+ m_debugId = o.m_debugId; m_name = o.m_name; m_objects = o.m_objects;
+ m_contexts = o.m_contexts;
+ return *this;
+}
+
+int QDeclarativeDebugContextReference::debugId() const
+{
+ return m_debugId;
+}
+
+QString QDeclarativeDebugContextReference::name() const
+{
+ return m_name;
+}
+
+QList<QDeclarativeDebugObjectReference> QDeclarativeDebugContextReference::objects() const
+{
+ return m_objects;
+}
+
+QList<QDeclarativeDebugContextReference> QDeclarativeDebugContextReference::contexts() const
+{
+ return m_contexts;
+}
+
+QDeclarativeDebugFileReference::QDeclarativeDebugFileReference()
+: m_lineNumber(-1), m_columnNumber(-1)
+{
+}
+
+QDeclarativeDebugFileReference::QDeclarativeDebugFileReference(const QDeclarativeDebugFileReference &o)
+: m_url(o.m_url), m_lineNumber(o.m_lineNumber), m_columnNumber(o.m_columnNumber)
+{
+}
+
+QDeclarativeDebugFileReference &QDeclarativeDebugFileReference::operator=(const QDeclarativeDebugFileReference &o)
+{
+ m_url = o.m_url; m_lineNumber = o.m_lineNumber; m_columnNumber = o.m_columnNumber;
+ return *this;
+}
+
+QUrl QDeclarativeDebugFileReference::url() const
+{
+ return m_url;
+}
+
+void QDeclarativeDebugFileReference::setUrl(const QUrl &u)
+{
+ m_url = u;
+}
+
+int QDeclarativeDebugFileReference::lineNumber() const
+{
+ return m_lineNumber;
+}
+
+void QDeclarativeDebugFileReference::setLineNumber(int l)
+{
+ m_lineNumber = l;
+}
+
+int QDeclarativeDebugFileReference::columnNumber() const
+{
+ return m_columnNumber;
+}
+
+void QDeclarativeDebugFileReference::setColumnNumber(int c)
+{
+ m_columnNumber = c;
+}
+
+QDeclarativeDebugPropertyReference::QDeclarativeDebugPropertyReference()
+: m_objectDebugId(-1), m_hasNotifySignal(false)
+{
+}
+
+QDeclarativeDebugPropertyReference::QDeclarativeDebugPropertyReference(const QDeclarativeDebugPropertyReference &o)
+: m_objectDebugId(o.m_objectDebugId), m_name(o.m_name), m_value(o.m_value),
+ m_valueTypeName(o.m_valueTypeName), m_binding(o.m_binding),
+ m_hasNotifySignal(o.m_hasNotifySignal)
+{
+}
+
+QDeclarativeDebugPropertyReference &QDeclarativeDebugPropertyReference::operator=(const QDeclarativeDebugPropertyReference &o)
+{
+ m_objectDebugId = o.m_objectDebugId; m_name = o.m_name; m_value = o.m_value;
+ m_valueTypeName = o.m_valueTypeName; m_binding = o.m_binding;
+ m_hasNotifySignal = o.m_hasNotifySignal;
+ return *this;
+}
+
+int QDeclarativeDebugPropertyReference::objectDebugId() const
+{
+ return m_objectDebugId;
+}
+
+QString QDeclarativeDebugPropertyReference::name() const
+{
+ return m_name;
+}
+
+QString QDeclarativeDebugPropertyReference::valueTypeName() const
+{
+ return m_valueTypeName;
+}
+
+QVariant QDeclarativeDebugPropertyReference::value() const
+{
+ return m_value;
+}
+
+QString QDeclarativeDebugPropertyReference::binding() const
+{
+ return m_binding;
+}
+
+bool QDeclarativeDebugPropertyReference::hasNotifySignal() const
+{
+ return m_hasNotifySignal;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/debugger/qdeclarativeenginedebug_p.h b/src/declarative/debugger/qdeclarativeenginedebug_p.h
new file mode 100644
index 00000000..6c00efca
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeenginedebug_p.h
@@ -0,0 +1,387 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QDECLARATIVEENGINEDEBUG_H
+#define QDECLARATIVEENGINEDEBUG_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+#include <private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeDebugConnection;
+class QDeclarativeDebugWatch;
+class QDeclarativeDebugPropertyWatch;
+class QDeclarativeDebugObjectExpressionWatch;
+class QDeclarativeDebugEnginesQuery;
+class QDeclarativeDebugRootContextQuery;
+class QDeclarativeDebugObjectQuery;
+class QDeclarativeDebugExpressionQuery;
+class QDeclarativeDebugPropertyReference;
+class QDeclarativeDebugContextReference;
+class QDeclarativeDebugObjectReference;
+class QDeclarativeDebugFileReference;
+class QDeclarativeDebugEngineReference;
+class QDeclarativeEngineDebugPrivate;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeEngineDebug : public QObject
+{
+Q_OBJECT
+public:
+ enum Status { NotConnected, Unavailable, Enabled };
+
+ explicit QDeclarativeEngineDebug(QDeclarativeDebugConnection *, QObject * = 0);
+
+ Status status() const;
+
+ QDeclarativeDebugPropertyWatch *addWatch(const QDeclarativeDebugPropertyReference &,
+ QObject *parent = 0);
+ QDeclarativeDebugWatch *addWatch(const QDeclarativeDebugContextReference &, const QString &,
+ QObject *parent = 0);
+ QDeclarativeDebugObjectExpressionWatch *addWatch(const QDeclarativeDebugObjectReference &, const QString &,
+ QObject *parent = 0);
+ QDeclarativeDebugWatch *addWatch(const QDeclarativeDebugObjectReference &,
+ QObject *parent = 0);
+ QDeclarativeDebugWatch *addWatch(const QDeclarativeDebugFileReference &,
+ QObject *parent = 0);
+
+ void removeWatch(QDeclarativeDebugWatch *watch);
+
+ QDeclarativeDebugEnginesQuery *queryAvailableEngines(QObject *parent = 0);
+ QDeclarativeDebugRootContextQuery *queryRootContexts(const QDeclarativeDebugEngineReference &,
+ QObject *parent = 0);
+ QDeclarativeDebugObjectQuery *queryObject(const QDeclarativeDebugObjectReference &,
+ QObject *parent = 0);
+ QDeclarativeDebugObjectQuery *queryObjectRecursive(const QDeclarativeDebugObjectReference &,
+ QObject *parent = 0);
+ QDeclarativeDebugExpressionQuery *queryExpressionResult(int objectDebugId,
+ const QString &expr,
+ QObject *parent = 0);
+ bool setBindingForObject(int objectDebugId, const QString &propertyName,
+ const QVariant &bindingExpression, bool isLiteralValue,
+ QString source = QString(), int line = -1);
+ bool resetBindingForObject(int objectDebugId, const QString &propertyName);
+ bool setMethodBody(int objectDebugId, const QString &methodName, const QString &methodBody);
+
+Q_SIGNALS:
+ void newObjects();
+ void statusChanged(Status status);
+
+private:
+ Q_DECLARE_PRIVATE(QDeclarativeEngineDebug)
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugWatch : public QObject
+{
+Q_OBJECT
+public:
+ enum State { Waiting, Active, Inactive, Dead };
+
+ QDeclarativeDebugWatch(QObject *);
+ ~QDeclarativeDebugWatch();
+
+ int queryId() const;
+ int objectDebugId() const;
+ State state() const;
+
+Q_SIGNALS:
+ void stateChanged(QDeclarativeDebugWatch::State);
+ //void objectChanged(int, const QDeclarativeDebugObjectReference &);
+ //void valueChanged(int, const QVariant &);
+
+ // Server sends value as string if it is a user-type variant
+ void valueChanged(const QByteArray &name, const QVariant &value);
+
+private:
+ friend class QDeclarativeEngineDebug;
+ friend class QDeclarativeEngineDebugPrivate;
+ void setState(State);
+ State m_state;
+ int m_queryId;
+ QDeclarativeEngineDebug *m_client;
+ int m_objectDebugId;
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugPropertyWatch : public QDeclarativeDebugWatch
+{
+ Q_OBJECT
+public:
+ QDeclarativeDebugPropertyWatch(QObject *parent);
+
+ QString name() const;
+
+private:
+ friend class QDeclarativeEngineDebug;
+ QString m_name;
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugObjectExpressionWatch : public QDeclarativeDebugWatch
+{
+ Q_OBJECT
+public:
+ QDeclarativeDebugObjectExpressionWatch(QObject *parent);
+
+ QString expression() const;
+
+private:
+ friend class QDeclarativeEngineDebug;
+ QString m_expr;
+ int m_debugId;
+};
+
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugQuery : public QObject
+{
+Q_OBJECT
+public:
+ enum State { Waiting, Error, Completed };
+
+ State state() const;
+ bool isWaiting() const;
+
+// bool waitUntilCompleted();
+
+Q_SIGNALS:
+ void stateChanged(QDeclarativeDebugQuery::State);
+
+protected:
+ QDeclarativeDebugQuery(QObject *);
+
+private:
+ friend class QDeclarativeEngineDebug;
+ friend class QDeclarativeEngineDebugPrivate;
+ void setState(State);
+ State m_state;
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugFileReference
+{
+public:
+ QDeclarativeDebugFileReference();
+ QDeclarativeDebugFileReference(const QDeclarativeDebugFileReference &);
+ QDeclarativeDebugFileReference &operator=(const QDeclarativeDebugFileReference &);
+
+ QUrl url() const;
+ void setUrl(const QUrl &);
+ int lineNumber() const;
+ void setLineNumber(int);
+ int columnNumber() const;
+ void setColumnNumber(int);
+
+private:
+ friend class QDeclarativeEngineDebugPrivate;
+ QUrl m_url;
+ int m_lineNumber;
+ int m_columnNumber;
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugEngineReference
+{
+public:
+ QDeclarativeDebugEngineReference();
+ QDeclarativeDebugEngineReference(int);
+ QDeclarativeDebugEngineReference(const QDeclarativeDebugEngineReference &);
+ QDeclarativeDebugEngineReference &operator=(const QDeclarativeDebugEngineReference &);
+
+ int debugId() const;
+ QString name() const;
+
+private:
+ friend class QDeclarativeEngineDebugPrivate;
+ int m_debugId;
+ QString m_name;
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugObjectReference
+{
+public:
+ QDeclarativeDebugObjectReference();
+ QDeclarativeDebugObjectReference(int);
+ QDeclarativeDebugObjectReference(const QDeclarativeDebugObjectReference &);
+ QDeclarativeDebugObjectReference &operator=(const QDeclarativeDebugObjectReference &);
+
+ int debugId() const;
+ QString className() const;
+ QString idString() const;
+ QString name() const;
+
+ QDeclarativeDebugFileReference source() const;
+ int contextDebugId() const;
+
+ QList<QDeclarativeDebugPropertyReference> properties() const;
+ QList<QDeclarativeDebugObjectReference> children() const;
+
+private:
+ friend class QDeclarativeEngineDebugPrivate;
+ int m_debugId;
+ QString m_class;
+ QString m_idString;
+ QString m_name;
+ QDeclarativeDebugFileReference m_source;
+ int m_contextDebugId;
+ QList<QDeclarativeDebugPropertyReference> m_properties;
+ QList<QDeclarativeDebugObjectReference> m_children;
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugContextReference
+{
+public:
+ QDeclarativeDebugContextReference();
+ QDeclarativeDebugContextReference(const QDeclarativeDebugContextReference &);
+ QDeclarativeDebugContextReference &operator=(const QDeclarativeDebugContextReference &);
+
+ int debugId() const;
+ QString name() const;
+
+ QList<QDeclarativeDebugObjectReference> objects() const;
+ QList<QDeclarativeDebugContextReference> contexts() const;
+
+private:
+ friend class QDeclarativeEngineDebugPrivate;
+ int m_debugId;
+ QString m_name;
+ QList<QDeclarativeDebugObjectReference> m_objects;
+ QList<QDeclarativeDebugContextReference> m_contexts;
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugPropertyReference
+{
+public:
+ QDeclarativeDebugPropertyReference();
+ QDeclarativeDebugPropertyReference(const QDeclarativeDebugPropertyReference &);
+ QDeclarativeDebugPropertyReference &operator=(const QDeclarativeDebugPropertyReference &);
+
+ int objectDebugId() const;
+ QString name() const;
+ QVariant value() const;
+ QString valueTypeName() const;
+ QString binding() const;
+ bool hasNotifySignal() const;
+
+private:
+ friend class QDeclarativeEngineDebugPrivate;
+ int m_objectDebugId;
+ QString m_name;
+ QVariant m_value;
+ QString m_valueTypeName;
+ QString m_binding;
+ bool m_hasNotifySignal;
+};
+
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugEnginesQuery : public QDeclarativeDebugQuery
+{
+Q_OBJECT
+public:
+ virtual ~QDeclarativeDebugEnginesQuery();
+ QList<QDeclarativeDebugEngineReference> engines() const;
+private:
+ friend class QDeclarativeEngineDebug;
+ friend class QDeclarativeEngineDebugPrivate;
+ QDeclarativeDebugEnginesQuery(QObject *);
+ QDeclarativeEngineDebug *m_client;
+ int m_queryId;
+ QList<QDeclarativeDebugEngineReference> m_engines;
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugRootContextQuery : public QDeclarativeDebugQuery
+{
+Q_OBJECT
+public:
+ virtual ~QDeclarativeDebugRootContextQuery();
+ QDeclarativeDebugContextReference rootContext() const;
+private:
+ friend class QDeclarativeEngineDebug;
+ friend class QDeclarativeEngineDebugPrivate;
+ QDeclarativeDebugRootContextQuery(QObject *);
+ QDeclarativeEngineDebug *m_client;
+ int m_queryId;
+ QDeclarativeDebugContextReference m_context;
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugObjectQuery : public QDeclarativeDebugQuery
+{
+Q_OBJECT
+public:
+ virtual ~QDeclarativeDebugObjectQuery();
+ QDeclarativeDebugObjectReference object() const;
+private:
+ friend class QDeclarativeEngineDebug;
+ friend class QDeclarativeEngineDebugPrivate;
+ QDeclarativeDebugObjectQuery(QObject *);
+ QDeclarativeEngineDebug *m_client;
+ int m_queryId;
+ QDeclarativeDebugObjectReference m_object;
+
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugExpressionQuery : public QDeclarativeDebugQuery
+{
+Q_OBJECT
+public:
+ virtual ~QDeclarativeDebugExpressionQuery();
+ QVariant expression() const;
+ QVariant result() const;
+private:
+ friend class QDeclarativeEngineDebug;
+ friend class QDeclarativeEngineDebugPrivate;
+ QDeclarativeDebugExpressionQuery(QObject *);
+ QDeclarativeEngineDebug *m_client;
+ int m_queryId;
+ QVariant m_expr;
+ QVariant m_result;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QDeclarativeDebugEngineReference)
+Q_DECLARE_METATYPE(QDeclarativeDebugObjectReference)
+Q_DECLARE_METATYPE(QDeclarativeDebugContextReference)
+Q_DECLARE_METATYPE(QDeclarativeDebugPropertyReference)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEENGINEDEBUG_H
diff --git a/src/declarative/debugger/qdeclarativeenginedebugservice.cpp b/src/declarative/debugger/qdeclarativeenginedebugservice.cpp
new file mode 100644
index 00000000..421e3994
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeenginedebugservice.cpp
@@ -0,0 +1,747 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativeenginedebugservice_p.h"
+
+#include "private/qdeclarativeboundsignal_p.h"
+#include "qdeclarativeengine.h"
+#include "private/qdeclarativemetatype_p.h"
+#include "qdeclarativeproperty.h"
+#include "private/qdeclarativeproperty_p.h"
+#include "private/qdeclarativebinding_p.h"
+#include "private/qdeclarativecontext_p.h"
+#include "private/qdeclarativewatcher_p.h"
+#include "private/qdeclarativevaluetype_p.h"
+#include "private/qdeclarativevmemetaobject_p.h"
+#include "private/qdeclarativeexpression_p.h"
+#include "private/qdeclarativepropertychanges_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qmetaobject.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QDeclarativeEngineDebugService, qmlEngineDebugService);
+
+QDeclarativeEngineDebugService *QDeclarativeEngineDebugService::instance()
+{
+ return qmlEngineDebugService();
+}
+
+QDeclarativeEngineDebugService::QDeclarativeEngineDebugService(QObject *parent)
+: QDeclarativeDebugService(QLatin1String("QDeclarativeEngine"), parent),
+ m_watch(new QDeclarativeWatcher(this))
+{
+ QObject::connect(m_watch, SIGNAL(propertyChanged(int,int,QMetaProperty,QVariant)),
+ this, SLOT(propertyChanged(int,int,QMetaProperty,QVariant)));
+}
+
+QDataStream &operator<<(QDataStream &ds,
+ const QDeclarativeEngineDebugService::QDeclarativeObjectData &data)
+{
+ ds << data.url << data.lineNumber << data.columnNumber << data.idString
+ << data.objectName << data.objectType << data.objectId << data.contextId;
+ return ds;
+}
+
+QDataStream &operator>>(QDataStream &ds,
+ QDeclarativeEngineDebugService::QDeclarativeObjectData &data)
+{
+ ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
+ >> data.objectName >> data.objectType >> data.objectId >> data.contextId;
+ return ds;
+}
+
+QDataStream &operator<<(QDataStream &ds,
+ const QDeclarativeEngineDebugService::QDeclarativeObjectProperty &data)
+{
+ ds << (int)data.type << data.name << data.value << data.valueTypeName
+ << data.binding << data.hasNotifySignal;
+ return ds;
+}
+
+QDataStream &operator>>(QDataStream &ds,
+ QDeclarativeEngineDebugService::QDeclarativeObjectProperty &data)
+{
+ int type;
+ ds >> type >> data.name >> data.value >> data.valueTypeName
+ >> data.binding >> data.hasNotifySignal;
+ data.type = (QDeclarativeEngineDebugService::QDeclarativeObjectProperty::Type)type;
+ return ds;
+}
+
+static inline bool isSignalPropertyName(const QString &signalName)
+{
+ // see QmlCompiler::isSignalPropertyName
+ return signalName.length() >= 3 && signalName.startsWith(QLatin1String("on")) &&
+ signalName.at(2).isLetter() && signalName.at(2).isUpper();
+}
+
+static bool hasValidSignal(QObject *object, const QString &propertyName)
+{
+ if (!isSignalPropertyName(propertyName))
+ return false;
+
+ QString signalName = propertyName.mid(2);
+ signalName[0] = signalName.at(0).toLower();
+
+ int sigIdx = QDeclarativePropertyPrivate::findSignalByName(object->metaObject(), signalName.toLatin1()).methodIndex();
+
+ if (sigIdx == -1)
+ return false;
+
+ return true;
+}
+
+QDeclarativeEngineDebugService::QDeclarativeObjectProperty
+QDeclarativeEngineDebugService::propertyData(QObject *obj, int propIdx)
+{
+ QDeclarativeObjectProperty rv;
+
+ QMetaProperty prop = obj->metaObject()->property(propIdx);
+
+ rv.type = QDeclarativeObjectProperty::Unknown;
+ rv.valueTypeName = QString::fromUtf8(prop.typeName());
+ rv.name = QString::fromUtf8(prop.name());
+ rv.hasNotifySignal = prop.hasNotifySignal();
+ QDeclarativeAbstractBinding *binding =
+ QDeclarativePropertyPrivate::binding(QDeclarativeProperty(obj, rv.name));
+ if (binding)
+ rv.binding = binding->expression();
+
+ if (QDeclarativeValueTypeFactory::isValueType(prop.userType())) {
+ rv.type = QDeclarativeObjectProperty::Basic;
+ } else if (QDeclarativeMetaType::isQObject(prop.userType())) {
+ rv.type = QDeclarativeObjectProperty::Object;
+ } else if (QDeclarativeMetaType::isList(prop.userType())) {
+ rv.type = QDeclarativeObjectProperty::List;
+ }
+
+ QVariant value;
+ if (rv.type != QDeclarativeObjectProperty::Unknown && prop.userType() != 0) {
+ value = prop.read(obj);
+ }
+ rv.value = valueContents(value);
+
+ return rv;
+}
+
+QVariant QDeclarativeEngineDebugService::valueContents(const QVariant &value) const
+{
+ int userType = value.userType();
+
+ if (value.type() == QVariant::List) {
+ QVariantList contents;
+ QVariantList list = value.toList();
+ int count = list.size();
+ for (int i = 0; i < count; i++)
+ contents << valueContents(list.at(i));
+ return contents;
+ }
+
+ if (QDeclarativeValueTypeFactory::isValueType(userType))
+ return value;
+
+ if (QDeclarativeMetaType::isQObject(userType)) {
+ QObject *o = QDeclarativeMetaType::toQObject(value);
+ if (o) {
+ QString name = o->objectName();
+ if (name.isEmpty())
+ name = QLatin1String("<unnamed object>");
+ return name;
+ }
+ }
+
+ return QLatin1String("<unknown value>");
+}
+
+void QDeclarativeEngineDebugService::buildObjectDump(QDataStream &message,
+ QObject *object, bool recur, bool dumpProperties)
+{
+ message << objectData(object);
+
+ QObjectList children = object->children();
+
+ int childrenCount = children.count();
+ for (int ii = 0; ii < children.count(); ++ii) {
+ if (qobject_cast<QDeclarativeContext*>(children[ii]) || QDeclarativeBoundSignal::cast(children[ii]))
+ --childrenCount;
+ }
+
+ message << childrenCount << recur;
+
+ QList<QDeclarativeObjectProperty> fakeProperties;
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+ if (qobject_cast<QDeclarativeContext*>(child))
+ continue;
+ QDeclarativeBoundSignal *signal = QDeclarativeBoundSignal::cast(child);
+ if (signal) {
+ if (!dumpProperties)
+ continue;
+ QDeclarativeObjectProperty prop;
+ prop.type = QDeclarativeObjectProperty::SignalProperty;
+ prop.hasNotifySignal = false;
+ QDeclarativeExpression *expr = signal->expression();
+ if (expr) {
+ prop.value = expr->expression();
+ QObject *scope = expr->scopeObject();
+ if (scope) {
+ QString sig = QLatin1String(scope->metaObject()->method(signal->index()).signature());
+ int lparen = sig.indexOf(QLatin1Char('('));
+ if (lparen >= 0) {
+ QString methodName = sig.mid(0, lparen);
+ prop.name = QLatin1String("on") + methodName[0].toUpper()
+ + methodName.mid(1);
+ }
+ }
+ }
+ fakeProperties << prop;
+ } else {
+ if (recur)
+ buildObjectDump(message, child, recur, dumpProperties);
+ else
+ message << objectData(child);
+ }
+ }
+
+ if (!dumpProperties) {
+ message << 0;
+ return;
+ }
+
+ QList<int> propertyIndexes;
+ for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) {
+ if (object->metaObject()->property(ii).isScriptable())
+ propertyIndexes << ii;
+ }
+
+ message << propertyIndexes.size() + fakeProperties.count();
+
+ for (int ii = 0; ii < propertyIndexes.size(); ++ii)
+ message << propertyData(object, propertyIndexes.at(ii));
+
+ for (int ii = 0; ii < fakeProperties.count(); ++ii)
+ message << fakeProperties[ii];
+}
+
+void QDeclarativeEngineDebugService::prepareDeferredObjects(QObject *obj)
+{
+ qmlExecuteDeferred(obj);
+
+ QObjectList children = obj->children();
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+ prepareDeferredObjects(child);
+ }
+
+}
+
+void QDeclarativeEngineDebugService::buildObjectList(QDataStream &message, QDeclarativeContext *ctxt)
+{
+ QDeclarativeContextData *p = QDeclarativeContextData::get(ctxt);
+
+ QString ctxtName = ctxt->objectName();
+ int ctxtId = QDeclarativeDebugService::idForObject(ctxt);
+
+ message << ctxtName << ctxtId;
+
+ int count = 0;
+
+ QDeclarativeContextData *child = p->childContexts;
+ while (child) {
+ ++count;
+ child = child->nextChild;
+ }
+
+ message << count;
+
+ child = p->childContexts;
+ while (child) {
+ buildObjectList(message, child->asQDeclarativeContext());
+ child = child->nextChild;
+ }
+
+ // Clean deleted objects
+ QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(ctxt);
+ for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
+ if (!ctxtPriv->instances.at(ii)) {
+ ctxtPriv->instances.removeAt(ii);
+ --ii;
+ }
+ }
+
+ message << ctxtPriv->instances.count();
+ for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
+ message << objectData(ctxtPriv->instances.at(ii));
+ }
+}
+
+void QDeclarativeEngineDebugService::buildStatesList(QDeclarativeContext *ctxt, bool cleanList=false)
+{
+ 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 QDeclarativeEngineDebugService::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));
+ }
+}
+
+QDeclarativeEngineDebugService::QDeclarativeObjectData
+QDeclarativeEngineDebugService::objectData(QObject *object)
+{
+ QDeclarativeData *ddata = QDeclarativeData::get(object);
+ QDeclarativeObjectData rv;
+ if (ddata && ddata->outerContext) {
+ rv.url = ddata->outerContext->url;
+ rv.lineNumber = ddata->lineNumber;
+ rv.columnNumber = ddata->columnNumber;
+ } else {
+ rv.lineNumber = -1;
+ rv.columnNumber = -1;
+ }
+
+ QDeclarativeContext *context = qmlContext(object);
+ if (context) {
+ QDeclarativeContextData *cdata = QDeclarativeContextData::get(context);
+ if (cdata)
+ rv.idString = cdata->findObjectId(object);
+ }
+
+ rv.objectName = object->objectName();
+ rv.objectId = QDeclarativeDebugService::idForObject(object);
+ rv.contextId = QDeclarativeDebugService::idForObject(qmlContext(object));
+
+ QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
+ if (type) {
+ QString typeName = QLatin1String(type->qmlTypeName());
+ int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
+ rv.objectType = lastSlash < 0 ? typeName : typeName.mid(lastSlash+1);
+ } else {
+ rv.objectType = QString::fromUtf8(object->metaObject()->className());
+ int marker = rv.objectType.indexOf(QLatin1String("_QMLTYPE_"));
+ if (marker != -1)
+ rv.objectType = rv.objectType.left(marker);
+ }
+
+ return rv;
+}
+
+void QDeclarativeEngineDebugService::messageReceived(const QByteArray &message)
+{
+ QDataStream ds(message);
+
+ QByteArray type;
+ ds >> type;
+
+ if (type == "LIST_ENGINES") {
+ int queryId;
+ ds >> queryId;
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("LIST_ENGINES_R");
+ rs << queryId << m_engines.count();
+
+ for (int ii = 0; ii < m_engines.count(); ++ii) {
+ QDeclarativeEngine *engine = m_engines.at(ii);
+
+ QString engineName = engine->objectName();
+ int engineId = QDeclarativeDebugService::idForObject(engine);
+
+ rs << engineName << engineId;
+ }
+
+ sendMessage(reply);
+ } else if (type == "LIST_OBJECTS") {
+ int queryId;
+ int engineId = -1;
+ ds >> queryId >> engineId;
+
+ QDeclarativeEngine *engine =
+ qobject_cast<QDeclarativeEngine *>(QDeclarativeDebugService::objectForId(engineId));
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("LIST_OBJECTS_R") << queryId;
+
+ if (engine) {
+ buildObjectList(rs, engine->rootContext());
+ buildStatesList(engine->rootContext(), true);
+ }
+
+ sendMessage(reply);
+ } else if (type == "FETCH_OBJECT") {
+ int queryId;
+ int objectId;
+ bool recurse;
+ bool dumpProperties = true;
+
+ ds >> queryId >> objectId >> recurse >> dumpProperties;
+
+ QObject *object = QDeclarativeDebugService::objectForId(objectId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("FETCH_OBJECT_R") << queryId;
+
+ if (object) {
+ if (recurse)
+ prepareDeferredObjects(object);
+ buildObjectDump(rs, object, recurse, dumpProperties);
+ }
+
+ sendMessage(reply);
+ } else if (type == "WATCH_OBJECT") {
+ int queryId;
+ int objectId;
+
+ ds >> queryId >> objectId;
+ bool ok = m_watch->addWatch(queryId, objectId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("WATCH_OBJECT_R") << queryId << ok;
+
+ sendMessage(reply);
+ } else if (type == "WATCH_PROPERTY") {
+ int queryId;
+ int objectId;
+ QByteArray property;
+
+ ds >> queryId >> objectId >> property;
+ bool ok = m_watch->addWatch(queryId, objectId, property);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("WATCH_PROPERTY_R") << queryId << ok;
+
+ sendMessage(reply);
+ } else if (type == "WATCH_EXPR_OBJECT") {
+ int queryId;
+ int debugId;
+ QString expr;
+
+ ds >> queryId >> debugId >> expr;
+ bool ok = m_watch->addWatch(queryId, debugId, expr);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("WATCH_EXPR_OBJECT_R") << queryId << ok;
+ sendMessage(reply);
+ } else if (type == "NO_WATCH") {
+ int queryId;
+
+ ds >> queryId;
+ m_watch->removeWatch(queryId);
+ } else if (type == "EVAL_EXPRESSION") {
+ int queryId;
+ int objectId;
+ QString expr;
+
+ ds >> queryId >> objectId >> expr;
+
+ QObject *object = QDeclarativeDebugService::objectForId(objectId);
+ QDeclarativeContext *context = qmlContext(object);
+ QVariant result;
+ if (object && context) {
+ QDeclarativeExpression exprObj(context, object, expr);
+ bool undefined = false;
+ QVariant value = exprObj.evaluate(&undefined);
+ if (undefined)
+ result = QLatin1String("<undefined>");
+ else
+ result = valueContents(value);
+ } else {
+ result = QLatin1String("<unknown context>");
+ }
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result;
+
+ sendMessage(reply);
+ } else if (type == "SET_BINDING") {
+ int objectId;
+ QString propertyName;
+ QVariant expr;
+ bool isLiteralValue;
+ QString filename;
+ int line;
+ ds >> objectId >> propertyName >> expr >> isLiteralValue;
+ if (!ds.atEnd()) { // backward compatibility from 2.1, 2.2
+ ds >> filename >> line;
+ }
+ setBinding(objectId, propertyName, expr, isLiteralValue, filename, line);
+ } else if (type == "RESET_BINDING") {
+ int objectId;
+ QString propertyName;
+ ds >> objectId >> propertyName;
+ resetBinding(objectId, propertyName);
+ } else if (type == "SET_METHOD_BODY") {
+ int objectId;
+ QString methodName;
+ QString methodBody;
+ ds >> objectId >> methodName >> methodBody;
+ setMethodBody(objectId, methodName, methodBody);
+ }
+}
+
+void QDeclarativeEngineDebugService::setBinding(int objectId,
+ const QString &propertyName,
+ const QVariant &expression,
+ bool isLiteralValue,
+ QString filename,
+ int line)
+{
+ QObject *object = objectForId(objectId);
+ QDeclarativeContext *context = qmlContext(object);
+
+ if (object && context) {
+ QDeclarativeProperty property(object, propertyName, context);
+ if (property.isValid()) {
+
+ bool inBaseState = true;
+
+ 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);
+ }
+ }
+ }
+
+ if (inBaseState) {
+ if (isLiteralValue) {
+ property.write(expression);
+ } else if (hasValidSignal(object, propertyName)) {
+ QDeclarativeExpression *declarativeExpression = new QDeclarativeExpression(context, object, expression.toString());
+ QDeclarativePropertyPrivate::setSignalExpression(property, declarativeExpression);
+ declarativeExpression->setSourceLocation(filename, line);
+ } else if (property.isProperty()) {
+ QDeclarativeBinding *binding = new QDeclarativeBinding(expression.toString(), object, context);
+ binding->setTarget(property);
+ binding->setSourceLocation(filename, line);
+ binding->setNotifyOnValueChanged(true);
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, binding);
+ if (oldBinding)
+ oldBinding->destroy();
+ binding->update();
+ } else {
+ qWarning() << "QDeclarativeEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
+ }
+ }
+
+ } else {
+ // not a valid property
+ if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
+ if (isLiteralValue) {
+ propertyChanges->changeValue(propertyName, expression);
+ } else {
+ propertyChanges->changeExpression(propertyName, expression.toString());
+ }
+ } else {
+ qWarning() << "QDeclarativeEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
+ }
+ }
+ }
+}
+
+void QDeclarativeEngineDebugService::resetBinding(int objectId, const QString &propertyName)
+{
+ QObject *object = objectForId(objectId);
+ QDeclarativeContext *context = qmlContext(object);
+
+ if (object && context) {
+ if (object->property(propertyName.toLatin1()).isValid()) {
+ QDeclarativeProperty property(object, propertyName);
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(property);
+ if (oldBinding) {
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, 0);
+ if (oldBinding)
+ oldBinding->destroy();
+ }
+ if (property.isResettable()) {
+ // Note: this will reset the property in any case, without regard to states
+ // Right now almost no QDeclarativeItem has reset methods for its properties (with the
+ // notable exception of QDeclarativeAnchors), so this is not a big issue
+ // later on, setBinding does take states into account
+ property.reset();
+ } else {
+ // overwrite with default value
+ if (QDeclarativeType *objType = QDeclarativeMetaType::qmlType(object->metaObject())) {
+ if (QObject *emptyObject = objType->create()) {
+ if (emptyObject->property(propertyName.toLatin1()).isValid()) {
+ QVariant defaultValue = QDeclarativeProperty(emptyObject, propertyName).read();
+ if (defaultValue.isValid()) {
+ setBinding(objectId, propertyName, defaultValue, true);
+ }
+ }
+ delete emptyObject;
+ }
+ }
+ }
+ } else if (hasValidSignal(object, propertyName)) {
+ QDeclarativeProperty property(object, propertyName, context);
+ QDeclarativePropertyPrivate::setSignalExpression(property, 0);
+ } else {
+ if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
+ propertyChanges->removeProperty(propertyName);
+ }
+ }
+ }
+}
+
+void QDeclarativeEngineDebugService::setMethodBody(int objectId, const QString &method, const QString &body)
+{
+ QObject *object = objectForId(objectId);
+ QDeclarativeContext *context = qmlContext(object);
+ if (!object || !context || !context->engine())
+ return;
+ QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
+ if (!contextData)
+ return;
+
+ QDeclarativePropertyCache::Data dummy;
+ QDeclarativePropertyCache::Data *prop =
+ QDeclarativePropertyCache::property(context->engine(), object, method, dummy);
+
+ if (!prop || !(prop->flags & QDeclarativePropertyCache::Data::IsVMEFunction))
+ return;
+
+ QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex);
+ QList<QByteArray> paramNames = metaMethod.parameterNames();
+
+ QString paramStr;
+ for (int ii = 0; ii < paramNames.count(); ++ii) {
+ if (ii != 0) paramStr.append(QLatin1String(","));
+ paramStr.append(QString::fromUtf8(paramNames.at(ii)));
+ }
+
+ QString jsfunction = QLatin1String("(function ") + method + QLatin1String("(") + paramStr +
+ QLatin1String(") {");
+ jsfunction += body;
+ jsfunction += QLatin1String("\n})");
+
+ QDeclarativeVMEMetaObject *vmeMetaObject =
+ static_cast<QDeclarativeVMEMetaObject*>(QObjectPrivate::get(object)->metaObject);
+ Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this
+
+ int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex);
+ vmeMetaObject->setVmeMethod(prop->coreIndex, QDeclarativeExpressionPrivate::evalInObjectScope(contextData, object, jsfunction, contextData->url.toString(), lineNumber, 0));
+}
+
+void QDeclarativeEngineDebugService::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
+{
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+
+ rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
+
+ sendMessage(reply);
+}
+
+void QDeclarativeEngineDebugService::addEngine(QDeclarativeEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(!m_engines.contains(engine));
+
+ m_engines.append(engine);
+}
+
+void QDeclarativeEngineDebugService::remEngine(QDeclarativeEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(m_engines.contains(engine));
+
+ m_engines.removeAll(engine);
+}
+
+void QDeclarativeEngineDebugService::objectCreated(QDeclarativeEngine *engine, QObject *object)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(m_engines.contains(engine));
+
+ int engineId = QDeclarativeDebugService::idForObject(engine);
+ int objectId = QDeclarativeDebugService::idForObject(object);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+
+ rs << QByteArray("OBJECT_CREATED") << engineId << objectId;
+ sendMessage(reply);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativeenginedebugservice_p.h b/src/declarative/debugger/qdeclarativeenginedebugservice_p.h
new file mode 100644
index 00000000..864fa13a
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeenginedebugservice_p.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEENGINEDEBUGSERVICE_P_H
+#define QDECLARATIVEENGINEDEBUGSERVICE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qdeclarativedebugservice_p.h>
+
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+#include <QWeakPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeEngine;
+class QDeclarativeContext;
+class QDeclarativeWatcher;
+class QDataStream;
+class QDeclarativeState;
+
+class QDeclarativeEngineDebugService : public QDeclarativeDebugService
+{
+ Q_OBJECT
+public:
+ QDeclarativeEngineDebugService(QObject * = 0);
+
+ struct QDeclarativeObjectData {
+ QUrl url;
+ int lineNumber;
+ int columnNumber;
+ QString idString;
+ QString objectName;
+ QString objectType;
+ int objectId;
+ int contextId;
+ };
+
+ struct QDeclarativeObjectProperty {
+ enum Type { Unknown, Basic, Object, List, SignalProperty };
+ Type type;
+ QString name;
+ QVariant value;
+ QString valueTypeName;
+ QString binding;
+ bool hasNotifySignal;
+ };
+
+ void addEngine(QDeclarativeEngine *);
+ void remEngine(QDeclarativeEngine *);
+ void objectCreated(QDeclarativeEngine *, QObject *);
+
+ static QDeclarativeEngineDebugService *instance();
+
+protected:
+ virtual void messageReceived(const QByteArray &);
+
+private Q_SLOTS:
+ void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
+
+private:
+ void prepareDeferredObjects(QObject *);
+ void buildObjectList(QDataStream &, QDeclarativeContext *);
+ void buildObjectDump(QDataStream &, QObject *, bool, bool);
+ void buildStatesList(QDeclarativeContext *, bool);
+ void buildStatesList(QObject *obj);
+ QDeclarativeObjectData objectData(QObject *);
+ QDeclarativeObjectProperty propertyData(QObject *, int);
+ QVariant valueContents(const QVariant &defaultValue) const;
+ void setBinding(int objectId, const QString &propertyName, const QVariant &expression, bool isLiteralValue, QString filename = QString(), int line = -1);
+ void resetBinding(int objectId, const QString &propertyName);
+ void setMethodBody(int objectId, const QString &method, const QString &body);
+
+ QList<QDeclarativeEngine *> m_engines;
+ QDeclarativeWatcher *m_watch;
+ QList<QWeakPointer<QDeclarativeState> > m_allStates;
+};
+Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugService::QDeclarativeObjectData &);
+Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugService::QDeclarativeObjectData &);
+Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugService::QDeclarativeObjectProperty &);
+Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugService::QDeclarativeObjectProperty &);
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEENGINEDEBUGSERVICE_P_H
+
diff --git a/src/declarative/debugger/qdeclarativeinspectorinterface_p.h b/src/declarative/debugger/qdeclarativeinspectorinterface_p.h
new file mode 100644
index 00000000..bd7cd954
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeinspectorinterface_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEOBSERVERINTERFACE_H
+#define QDECLARATIVEOBSERVERINTERFACE_H
+
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QDeclarativeInspectorInterface
+{
+public:
+ QDeclarativeInspectorInterface() {}
+ virtual ~QDeclarativeInspectorInterface() {}
+
+ virtual void activate() = 0;
+ virtual void deactivate() = 0;
+};
+
+Q_DECLARE_INTERFACE(QDeclarativeInspectorInterface, "com.trolltech.Qt.QDeclarativeInspectorInterface/1.0")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEOBSERVERINTERFACE_H
diff --git a/src/declarative/debugger/qdeclarativeinspectorservice.cpp b/src/declarative/debugger/qdeclarativeinspectorservice.cpp
new file mode 100644
index 00000000..b651b259
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeinspectorservice.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativeinspectorservice_p.h"
+#include "private/qdeclarativeinspectorinterface_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QPluginLoader>
+
+#include <QtDeclarative/QDeclarativeView>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QDeclarativeInspectorService, serviceInstance)
+
+QDeclarativeInspectorService::QDeclarativeInspectorService()
+ : QDeclarativeDebugService(QLatin1String("QDeclarativeObserverMode"))
+ , m_inspectorPlugin(0)
+{
+}
+
+QDeclarativeInspectorService *QDeclarativeInspectorService::instance()
+{
+ return serviceInstance();
+}
+
+void QDeclarativeInspectorService::addView(QDeclarativeView *view)
+{
+ m_views.append(view);
+ updateStatus();
+}
+
+void QDeclarativeInspectorService::removeView(QDeclarativeView *view)
+{
+ m_views.removeAll(view);
+ updateStatus();
+}
+
+void QDeclarativeInspectorService::sendMessage(const QByteArray &message)
+{
+ if (status() != Enabled)
+ return;
+
+ QDeclarativeDebugService::sendMessage(message);
+}
+
+void QDeclarativeInspectorService::statusChanged(Status status)
+{
+ updateStatus();
+}
+
+void QDeclarativeInspectorService::updateStatus()
+{
+ if (m_views.isEmpty()) {
+ if (m_inspectorPlugin)
+ m_inspectorPlugin->deactivate();
+ return;
+ }
+
+ if (status() == Enabled) {
+ if (!m_inspectorPlugin)
+ m_inspectorPlugin = loadInspectorPlugin();
+
+ if (!m_inspectorPlugin) {
+ qWarning() << "Error while loading inspector plugin";
+ return;
+ }
+
+ m_inspectorPlugin->activate();
+ } else {
+ if (m_inspectorPlugin)
+ m_inspectorPlugin->deactivate();
+ }
+}
+
+void QDeclarativeInspectorService::messageReceived(const QByteArray &message)
+{
+ emit gotMessage(message);
+}
+
+QDeclarativeInspectorInterface *QDeclarativeInspectorService::loadInspectorPlugin()
+{
+ QStringList pluginCandidates;
+ const QStringList paths = QCoreApplication::libraryPaths();
+ foreach (const QString &libPath, paths) {
+ const QDir dir(libPath + QLatin1String("/qmltooling"));
+ if (dir.exists())
+ foreach (const QString &pluginPath, dir.entryList(QDir::Files))
+ pluginCandidates << dir.absoluteFilePath(pluginPath);
+ }
+
+ foreach (const QString &pluginPath, pluginCandidates) {
+ QPluginLoader loader(pluginPath);
+ if (!loader.load())
+ continue;
+
+ QDeclarativeInspectorInterface *inspector =
+ qobject_cast<QDeclarativeInspectorInterface*>(loader.instance());
+
+ if (inspector)
+ return inspector;
+ loader.unload();
+ }
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativeinspectorservice_p.h b/src/declarative/debugger/qdeclarativeinspectorservice_p.h
new file mode 100644
index 00000000..623e850a
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativeinspectorservice_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEOBSERVERSERVICE_H
+#define QDECLARATIVEOBSERVERSERVICE_H
+
+#include "private/qdeclarativedebugservice_p.h"
+#include <private/qdeclarativeglobal_p.h>
+
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeView;
+class QDeclarativeInspectorInterface;
+
+class Q_DECLARATIVE_EXPORT QDeclarativeInspectorService : public QDeclarativeDebugService
+{
+ Q_OBJECT
+
+public:
+ QDeclarativeInspectorService();
+ static QDeclarativeInspectorService *instance();
+
+ void addView(QDeclarativeView *);
+ void removeView(QDeclarativeView *);
+ QList<QDeclarativeView*> views() const { return m_views; }
+
+ void sendMessage(const QByteArray &message);
+
+Q_SIGNALS:
+ void gotMessage(const QByteArray &message);
+
+protected:
+ virtual void statusChanged(Status status);
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ void updateStatus();
+
+ static QDeclarativeInspectorInterface *loadInspectorPlugin();
+
+ QList<QDeclarativeView*> m_views;
+ QDeclarativeInspectorInterface *m_inspectorPlugin;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEOBSERVERSERVICE_H
diff --git a/src/declarative/debugger/qjsdebuggeragent.cpp b/src/declarative/debugger/qjsdebuggeragent.cpp
new file mode 100644
index 00000000..9935ab11
--- /dev/null
+++ b/src/declarative/debugger/qjsdebuggeragent.cpp
@@ -0,0 +1,614 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qjsdebuggeragent_p.h"
+#include "private/qdeclarativedebughelper_p.h"
+#include "private/qjsdebugservice_p.h"
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qset.h>
+#include <QtCore/qurl.h>
+#include <QtScript/qscriptcontextinfo.h>
+#include <QtScript/qscriptengine.h>
+#include <QtScript/qscriptvalueiterator.h>
+
+QT_BEGIN_NAMESPACE
+
+class QJSDebuggerAgentPrivate
+{
+public:
+ QJSDebuggerAgentPrivate(QJSDebuggerAgent *q)
+ : q(q), state(NoState), isInitialized(false), coverageEnabled(false)
+ {}
+
+ void continueExec();
+ void recordKnownObjects(const QList<JSAgentWatchData> &);
+ QList<JSAgentWatchData> getLocals(QScriptContext *);
+ void positionChange(qint64 scriptId, int lineNumber, int columnNumber);
+ QScriptEngine *engine() { return q->engine(); }
+ void stopped();
+
+public:
+ QJSDebuggerAgent *q;
+ JSDebuggerState state;
+ int stepDepth;
+ int stepCount;
+
+ QEventLoop loop;
+ QHash<qint64, QString> filenames;
+ JSAgentBreakpoints breakpoints;
+ // breakpoints by filename (without path)
+ QHash<QString, JSAgentBreakpointData> fileNameToBreakpoints;
+ QStringList watchExpressions;
+ QSet<qint64> knownObjectIds;
+ bool isInitialized;
+ bool coverageEnabled;
+};
+
+namespace {
+
+class SetupExecEnv
+{
+public:
+ SetupExecEnv(QJSDebuggerAgentPrivate *a)
+ : agent(a),
+ previousState(a->state),
+ hadException(a->engine()->hasUncaughtException())
+ {
+ agent->state = StoppedState;
+ }
+
+ ~SetupExecEnv()
+ {
+ if (!hadException && agent->engine()->hasUncaughtException())
+ agent->engine()->clearExceptions();
+ agent->state = previousState;
+ }
+
+private:
+ QJSDebuggerAgentPrivate *agent;
+ JSDebuggerState previousState;
+ bool hadException;
+};
+
+} // anonymous namespace
+
+static JSAgentWatchData fromScriptValue(const QString &expression,
+ const QScriptValue &value)
+{
+ static const QString arrayStr = QCoreApplication::translate
+ ("Debugger::JSAgentWatchData", "[Array of length %1]");
+ static const QString undefinedStr = QCoreApplication::translate
+ ("Debugger::JSAgentWatchData", "<undefined>");
+
+ JSAgentWatchData data;
+ data.exp = expression.toUtf8();
+ data.name = data.exp;
+ data.hasChildren = false;
+ data.value = value.toString().toUtf8();
+ data.objectId = value.objectId();
+ if (value.isArray()) {
+ data.type = "Array";
+ data.value = arrayStr.arg(value.property(QLatin1String("length")).toString()).toUtf8();
+ data.hasChildren = true;
+ } else if (value.isBool()) {
+ data.type = "Bool";
+ // data.value = value.toBool() ? "true" : "false";
+ } else if (value.isDate()) {
+ data.type = "Date";
+ data.value = value.toDateTime().toString().toUtf8();
+ } else if (value.isError()) {
+ data.type = "Error";
+ } else if (value.isFunction()) {
+ data.type = "Function";
+ } else if (value.isUndefined()) {
+ data.type = undefinedStr.toUtf8();
+ } else if (value.isNumber()) {
+ data.type = "Number";
+ } else if (value.isRegExp()) {
+ data.type = "RegExp";
+ } else if (value.isString()) {
+ data.type = "String";
+ } else if (value.isVariant()) {
+ data.type = "Variant";
+ } else if (value.isQObject()) {
+ const QObject *obj = value.toQObject();
+ data.type = "Object";
+ data.value += '[';
+ data.value += obj->metaObject()->className();
+ data.value += ']';
+ data.hasChildren = true;
+ } else if (value.isObject()) {
+ data.type = "Object";
+ data.hasChildren = true;
+ data.value = "[Object]";
+ } else if (value.isNull()) {
+ data.type = "<null>";
+ } else {
+ data.type = "<unknown>";
+ }
+ return data;
+}
+
+static QList<JSAgentWatchData> expandObject(const QScriptValue &object)
+{
+ QList<JSAgentWatchData> result;
+ QScriptValueIterator it(object);
+ while (it.hasNext()) {
+ it.next();
+ if (it.flags() & QScriptValue::SkipInEnumeration)
+ continue;
+ if (/*object.isQObject() &&*/ it.value().isFunction()) {
+ // Cosmetics: skip all functions and slot, there are too many of them,
+ // and it is not useful information in the debugger.
+ continue;
+ }
+ JSAgentWatchData data = fromScriptValue(it.name(), it.value());
+ result.append(data);
+ }
+ if (result.isEmpty()) {
+ JSAgentWatchData data;
+ data.name = "<no initialized data>";
+ data.hasChildren = false;
+ data.value = " ";
+ data.objectId = 0;
+ result.append(data);
+ }
+ return result;
+}
+
+static QString fileName(const QString &fileUrl)
+{
+ int lastDelimiterPos = fileUrl.lastIndexOf(QLatin1Char('/'));
+ return fileUrl.mid(lastDelimiterPos, fileUrl.size() - lastDelimiterPos);
+}
+
+void QJSDebuggerAgentPrivate::recordKnownObjects(const QList<JSAgentWatchData>& list)
+{
+ foreach (const JSAgentWatchData &data, list)
+ knownObjectIds << data.objectId;
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgentPrivate::getLocals(QScriptContext *ctx)
+{
+ QList<JSAgentWatchData> locals;
+ if (ctx) {
+ QScriptValue activationObject = ctx->activationObject();
+ QScriptValue thisObject = ctx->thisObject();
+ locals = expandObject(activationObject);
+ if (thisObject.isObject()
+ && thisObject.objectId() != engine()->globalObject().objectId()
+ && QScriptValueIterator(thisObject).hasNext())
+ locals.prepend(fromScriptValue(QLatin1String("this"), thisObject));
+ recordKnownObjects(locals);
+ knownObjectIds << activationObject.objectId();
+ }
+ return locals;
+}
+
+/*!
+ Constructs a new agent for the given \a engine. The agent will
+ report debugging-related events (e.g. step completion) to the given
+ \a backend.
+*/
+QJSDebuggerAgent::QJSDebuggerAgent(QScriptEngine *engine, QObject *parent)
+ : QObject(parent)
+ , QScriptEngineAgent(engine)
+ , d(new QJSDebuggerAgentPrivate(this))
+{
+ QJSDebuggerAgent::engine()->setAgent(this);
+}
+
+QJSDebuggerAgent::QJSDebuggerAgent(QDeclarativeEngine *engine, QObject *parent)
+ : QObject(parent)
+ , QScriptEngineAgent(QDeclarativeDebugHelper::getScriptEngine(engine))
+ , d(new QJSDebuggerAgentPrivate(this))
+{
+ QJSDebuggerAgent::engine()->setAgent(this);
+}
+
+/*!
+ Destroys this QJSDebuggerAgent.
+*/
+QJSDebuggerAgent::~QJSDebuggerAgent()
+{
+ engine()->setAgent(0);
+ delete d;
+}
+
+/*!
+ Indicates whether the agent got the list of breakpoints.
+ */
+bool QJSDebuggerAgent::isInitialized() const
+{
+ return d->isInitialized;
+}
+
+void QJSDebuggerAgent::setCoverageEnabled(bool enabled)
+{
+ d->isInitialized = true;
+ d->coverageEnabled = enabled;
+}
+
+void QJSDebuggerAgent::setBreakpoints(const JSAgentBreakpoints &breakpoints)
+{
+ d->breakpoints = breakpoints;
+
+ d->fileNameToBreakpoints.clear();
+ foreach (const JSAgentBreakpointData &bp, breakpoints)
+ d->fileNameToBreakpoints.insertMulti(fileName(QString::fromUtf8(bp.fileUrl)), bp);
+
+ d->isInitialized = true;
+}
+
+void QJSDebuggerAgent::setWatchExpressions(const QStringList &watchExpressions)
+{
+ d->watchExpressions = watchExpressions;
+}
+
+void QJSDebuggerAgent::stepOver()
+{
+ d->stepDepth = 0;
+ d->state = SteppingOverState;
+ d->continueExec();
+}
+
+void QJSDebuggerAgent::stepInto()
+{
+ d->stepDepth = 0;
+ d->state = SteppingIntoState;
+ d->continueExec();
+}
+
+void QJSDebuggerAgent::stepOut()
+{
+ d->stepDepth = 0;
+ d->state = SteppingOutState;
+ d->continueExec();
+}
+
+void QJSDebuggerAgent::continueExecution()
+{
+ d->state = NoState;
+ d->continueExec();
+}
+
+JSAgentWatchData QJSDebuggerAgent::executeExpression(const QString &expr)
+{
+ SetupExecEnv execEnv(d);
+
+ JSAgentWatchData data = fromScriptValue(expr, engine()->evaluate(expr));
+ d->knownObjectIds << data.objectId;
+ return data;
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgent::expandObjectById(quint64 objectId)
+{
+ SetupExecEnv execEnv(d);
+
+ QScriptValue v;
+ if (d->knownObjectIds.contains(objectId))
+ v = engine()->objectById(objectId);
+
+ QList<JSAgentWatchData> result = expandObject(v);
+ d->recordKnownObjects(result);
+ return result;
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgent::locals()
+{
+ SetupExecEnv execEnv(d);
+ return d->getLocals(engine()->currentContext());
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgent::localsAtFrame(int frameId)
+{
+ SetupExecEnv execEnv(d);
+
+ int deep = 0;
+ QScriptContext *ctx = engine()->currentContext();
+ while (ctx && deep < frameId) {
+ ctx = ctx->parentContext();
+ deep++;
+ }
+
+ return d->getLocals(ctx);
+}
+
+QList<JSAgentStackData> QJSDebuggerAgent::backtrace()
+{
+ SetupExecEnv execEnv(d);
+
+ QList<JSAgentStackData> backtrace;
+
+ for (QScriptContext *ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
+ QScriptContextInfo info(ctx);
+
+ JSAgentStackData frame;
+ frame.functionName = info.functionName().toUtf8();
+ if (frame.functionName.isEmpty()) {
+ if (ctx->parentContext()) {
+ switch (info.functionType()) {
+ case QScriptContextInfo::ScriptFunction:
+ frame.functionName = "<anonymous>";
+ break;
+ case QScriptContextInfo::NativeFunction:
+ frame.functionName = "<native>";
+ break;
+ case QScriptContextInfo::QtFunction:
+ case QScriptContextInfo::QtPropertyFunction:
+ frame.functionName = "<native slot>";
+ break;
+ }
+ } else {
+ frame.functionName = "<global>";
+ }
+ }
+ frame.lineNumber = info.lineNumber();
+ // if the line number is unknown, fallback to the function line number
+ if (frame.lineNumber == -1)
+ frame.lineNumber = info.functionStartLineNumber();
+
+ frame.fileUrl = info.fileName().toUtf8();
+ backtrace.append(frame);
+ }
+
+ return backtrace;
+}
+
+QList<JSAgentWatchData> QJSDebuggerAgent::watches()
+{
+ SetupExecEnv execEnv(d);
+
+ QList<JSAgentWatchData> watches;
+ foreach (const QString &expr, d->watchExpressions)
+ watches << fromScriptValue(expr, engine()->evaluate(expr));
+ d->recordKnownObjects(watches);
+ return watches;
+}
+
+void QJSDebuggerAgent::setProperty(qint64 objectId,
+ const QString &property,
+ const QString &value)
+{
+ SetupExecEnv execEnv(d);
+
+ if (d->knownObjectIds.contains(objectId)) {
+ QScriptValue object = engine()->objectById(objectId);
+ if (object.isObject()) {
+ QScriptValue result = engine()->evaluate(value);
+ object.setProperty(property, result);
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::scriptLoad(qint64 id, const QString &program,
+ const QString &fileName, int baseLineNumber)
+{
+ d->filenames.insert(id, fileName);
+
+ if (d->coverageEnabled) {
+ JSAgentCoverageData rd = {"COVERAGE", QJSDebugService::instance()->m_timer.elapsed(), (int)CoverageScriptLoad,
+ id, program, fileName, baseLineNumber,
+ 0, 0, QString()};
+ QJSDebugService::instance()->processMessage(rd);
+ }
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::scriptUnload(qint64 id)
+{
+ d->filenames.remove(id);
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::contextPush()
+{
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::contextPop()
+{
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::functionEntry(qint64 scriptId)
+{
+ d->stepDepth++;
+
+ if (d->coverageEnabled) {
+ JSAgentCoverageData rd = {"COVERAGE", QJSDebugService::instance()->m_timer.elapsed(), (int)CoverageFuncEntry,
+ scriptId, QString(), QString(), 0, 0, 0, QString()};
+ QJSDebugService::instance()->processMessage(rd);
+ QJSDebugService::instance()->m_timer.restart();
+ }
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue)
+{
+ d->stepDepth--;
+
+ if (d->coverageEnabled) {
+ JSAgentCoverageData rd = {"COVERAGE", QJSDebugService::instance()->m_timer.elapsed(), (int)CoverageFuncExit,
+ scriptId, QString(), QString(), 0, 0, 0, returnValue.toString()};
+ QJSDebugService::instance()->processMessage(rd);
+ }
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
+{
+ d->positionChange(scriptId, lineNumber, columnNumber);
+
+ if (d->coverageEnabled) {
+ JSAgentCoverageData rd = {"COVERAGE", QJSDebugService::instance()->m_timer.elapsed(), (int)CoveragePosChange,
+ scriptId, QString(), QString(), 0, lineNumber, columnNumber, QString()};
+ QJSDebugService::instance()->processMessage(rd);
+ }
+}
+
+void QJSDebuggerAgentPrivate::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
+{
+ Q_UNUSED(columnNumber);
+
+ if (state == StoppedState)
+ return; //no re-entrency
+
+ // check breakpoints
+ if (!breakpoints.isEmpty()) {
+ const QScriptContext *ctx = engine()->currentContext();
+ const QScriptContextInfo info(ctx);
+
+ if (info.functionType() == QScriptContextInfo::ScriptFunction) {
+ QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
+ // It is possible that the scripts are loaded before the agent is attached
+ if (it == filenames.constEnd()) {
+ it = filenames.insert(scriptId, info.fileName());
+ }
+
+ const QString filePath = it.value();
+ const JSAgentBreakpoints bps = fileNameToBreakpoints.values(fileName(filePath)).toSet();
+
+ foreach (const JSAgentBreakpointData &bp, bps) {
+ if (bp.lineNumber == lineNumber) {
+ stopped();
+ return;
+ }
+ }
+ }
+ }
+
+ switch (state) {
+ case NoState:
+ case StoppedState:
+ // Do nothing
+ break;
+ case SteppingOutState:
+ if (stepDepth >= 0)
+ break;
+ //fallthough
+ case SteppingOverState:
+ if (stepDepth > 0)
+ break;
+ //fallthough
+ case SteppingIntoState:
+ stopped();
+ break;
+ }
+
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::exceptionThrow(qint64 scriptId,
+ const QScriptValue &exception,
+ bool hasHandler)
+{
+ Q_UNUSED(scriptId);
+ Q_UNUSED(exception);
+ Q_UNUSED(hasHandler);
+// qDebug() << Q_FUNC_INFO << exception.toString() << hasHandler;
+#if 0 //sometimes, we get exceptions that we should just ignore.
+ if (!hasHandler && state != StoppedState)
+ stopped(true, exception);
+#endif
+}
+
+/*!
+ \reimp
+*/
+void QJSDebuggerAgent::exceptionCatch(qint64 scriptId, const QScriptValue &exception)
+{
+ Q_UNUSED(scriptId);
+ Q_UNUSED(exception);
+}
+
+bool QJSDebuggerAgent::supportsExtension(Extension extension) const
+{
+ return extension == QScriptEngineAgent::DebuggerInvocationRequest;
+}
+
+QVariant QJSDebuggerAgent::extension(Extension extension, const QVariant &argument)
+{
+ if (extension == QScriptEngineAgent::DebuggerInvocationRequest) {
+ d->stopped();
+ return QVariant();
+ }
+ return QScriptEngineAgent::extension(extension, argument);
+}
+
+void QJSDebuggerAgentPrivate::stopped()
+{
+ bool becauseOfException = false;
+ const QScriptValue &exception = QScriptValue();
+
+ knownObjectIds.clear();
+ state = StoppedState;
+
+ emit q->stopped(becauseOfException, exception.toString());
+
+ loop.exec(QEventLoop::ExcludeUserInputEvents);
+}
+
+void QJSDebuggerAgentPrivate::continueExec()
+{
+ loop.quit();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qjsdebuggeragent_p.h b/src/declarative/debugger/qjsdebuggeragent_p.h
new file mode 100644
index 00000000..a4ffc187
--- /dev/null
+++ b/src/declarative/debugger/qjsdebuggeragent_p.h
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QJSDEBUGGERAGENT_P_H
+#define QJSDEBUGGERAGENT_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 <QtScript/qscriptengineagent.h>
+#include <QtCore/qset.h>
+
+QT_BEGIN_NAMESPACE
+class QScriptValue;
+class QDeclarativeEngine;
+QT_END_NAMESPACE
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QJSDebuggerAgentPrivate;
+
+enum JSDebuggerState
+{
+ NoState,
+ SteppingIntoState,
+ SteppingOverState,
+ SteppingOutState,
+ StoppedState
+};
+
+enum JSCoverageMessage {
+ CoverageLocation,
+ CoverageScriptLoad,
+ CoveragePosChange,
+ CoverageFuncEntry,
+ CoverageFuncExit,
+ CoverageComplete,
+
+ CoverageMaximumMessage
+};
+
+struct JSAgentWatchData
+{
+ QByteArray exp;
+ QByteArray name;
+ QByteArray value;
+ QByteArray type;
+ bool hasChildren;
+ quint64 objectId;
+};
+
+inline QDataStream &operator<<(QDataStream &s, const JSAgentWatchData &data)
+{
+ return s << data.exp << data.name << data.value
+ << data.type << data.hasChildren << data.objectId;
+}
+
+inline QDataStream &operator>>(QDataStream &s, JSAgentWatchData &data)
+{
+ return s >> data.exp >> data.name >> data.value
+ >> data.type >> data.hasChildren >> data.objectId;
+}
+
+struct JSAgentStackData
+{
+ QByteArray functionName;
+ QByteArray fileUrl;
+ qint32 lineNumber;
+};
+
+inline QDataStream &operator<<(QDataStream &s, const JSAgentStackData &data)
+{
+ return s << data.functionName << data.fileUrl << data.lineNumber;
+}
+
+inline QDataStream &operator>>(QDataStream &s, JSAgentStackData &data)
+{
+ return s >> data.functionName >> data.fileUrl >> data.lineNumber;
+}
+
+struct JSAgentBreakpointData
+{
+ QByteArray functionName;
+ QByteArray fileUrl;
+ qint32 lineNumber;
+};
+
+typedef QSet<JSAgentBreakpointData> JSAgentBreakpoints;
+
+inline QDataStream &operator<<(QDataStream &s, const JSAgentBreakpointData &data)
+{
+ return s << data.functionName << data.fileUrl << data.lineNumber;
+}
+
+inline QDataStream &operator>>(QDataStream &s, JSAgentBreakpointData &data)
+{
+ return s >> data.functionName >> data.fileUrl >> data.lineNumber;
+}
+
+inline bool operator==(const JSAgentBreakpointData &b1, const JSAgentBreakpointData &b2)
+{
+ return b1.lineNumber == b2.lineNumber && b1.fileUrl == b2.fileUrl;
+}
+
+inline uint qHash(const JSAgentBreakpointData &b)
+{
+ return b.lineNumber ^ qHash(b.fileUrl);
+}
+
+
+class QJSDebuggerAgent : public QObject, public QScriptEngineAgent
+{
+ Q_OBJECT
+
+public:
+ QJSDebuggerAgent(QScriptEngine *engine, QObject *parent = 0);
+ QJSDebuggerAgent(QDeclarativeEngine *engine, QObject *parent = 0);
+ ~QJSDebuggerAgent();
+
+ bool isInitialized() const;
+
+ void setBreakpoints(const JSAgentBreakpoints &);
+ void setWatchExpressions(const QStringList &);
+
+ void stepOver();
+ void stepInto();
+ void stepOut();
+ void continueExecution();
+ void setCoverageEnabled(bool enabled);
+
+ JSAgentWatchData executeExpression(const QString &expr);
+ QList<JSAgentWatchData> expandObjectById(quint64 objectId);
+ QList<JSAgentWatchData> locals();
+ QList<JSAgentWatchData> localsAtFrame(int frameId);
+ QList<JSAgentStackData> backtrace();
+ QList<JSAgentWatchData> watches();
+ void setProperty(qint64 objectId,
+ const QString &property,
+ const QString &value);
+
+ // reimplemented
+ void scriptLoad(qint64 id, const QString &program,
+ const QString &fileName, int baseLineNumber);
+ void scriptUnload(qint64 id);
+
+ void contextPush();
+ void contextPop();
+
+ void functionEntry(qint64 scriptId);
+ void functionExit(qint64 scriptId,
+ const QScriptValue &returnValue);
+
+ void positionChange(qint64 scriptId,
+ int lineNumber, int columnNumber);
+
+ void exceptionThrow(qint64 scriptId,
+ const QScriptValue &exception,
+ bool hasHandler);
+ void exceptionCatch(qint64 scriptId,
+ const QScriptValue &exception);
+
+ bool supportsExtension(Extension extension) const;
+ QVariant extension(Extension extension,
+ const QVariant &argument = QVariant());
+
+Q_SIGNALS:
+ void stopped(bool becauseOfException,
+ const QString &exception);
+
+private:
+ friend class QJSDebuggerAgentPrivate;
+ QJSDebuggerAgentPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QJSDEBUGGERAGENT_P_H
diff --git a/src/declarative/debugger/qjsdebugservice.cpp b/src/declarative/debugger/qjsdebugservice.cpp
new file mode 100644
index 00000000..686710dc
--- /dev/null
+++ b/src/declarative/debugger/qjsdebugservice.cpp
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qjsdebugservice_p.h"
+#include "private/qjsdebuggeragent_p.h"
+
+#include <QtCore/qdatastream.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+
+Q_GLOBAL_STATIC(QJSDebugService, serviceInstance)
+
+// convert to a QByteArray that can be sent to the debug client
+QByteArray JSAgentCoverageData::toByteArray() const
+{
+ QByteArray data;
+ //### using QDataStream is relatively expensive
+ QDataStream ds(&data, QIODevice::WriteOnly);
+ ds << prefix << time << messageType << scriptId << program << fileName << baseLineNumber
+ << lineNumber << columnNumber << returnValue;
+ return data;
+}
+
+QJSDebugService::QJSDebugService(QObject *parent)
+ : QDeclarativeDebugService(QLatin1String("JSDebugger"), parent)
+ , m_agent(0), m_deferredSend(true)
+{
+ m_timer.start();
+}
+
+QJSDebugService::~QJSDebugService()
+{
+ delete m_agent;
+}
+
+QJSDebugService *QJSDebugService::instance()
+{
+ return serviceInstance();
+}
+
+void QJSDebugService::addEngine(QDeclarativeEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(!m_engines.contains(engine));
+
+ m_engines.append(engine);
+
+ if (status() == Enabled && !m_engines.isEmpty() && !m_agent) {
+ m_agent = new QJSDebuggerAgent(engine, engine);
+ connect(m_agent, SIGNAL(stopped(bool,QString)),
+ this, SLOT(executionStopped(bool,QString)));
+
+ while (!m_agent->isInitialized()) {
+ waitForMessage();
+ }
+ }
+}
+
+void QJSDebugService::removeEngine(QDeclarativeEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(m_engines.contains(engine));
+
+ m_engines.removeAll(engine);
+}
+
+void QJSDebugService::statusChanged(Status status)
+{
+ if (status == Enabled && !m_engines.isEmpty() && !m_agent) {
+ // Multiple engines are currently unsupported
+ QDeclarativeEngine *engine = m_engines.first();
+ m_agent = new QJSDebuggerAgent(engine, engine);
+
+ connect(m_agent, SIGNAL(stopped(bool,QString)),
+ this, SLOT(executionStopped(bool,QString)));
+
+ } else if (status != Enabled && m_agent) {
+ delete m_agent;
+ m_agent = 0;
+ }
+}
+
+void QJSDebugService::messageReceived(const QByteArray &message)
+{
+ if (!m_agent) {
+ qWarning() << "QJSDebugService::messageReceived: No QJSDebuggerAgent available";
+ return;
+ }
+
+ QDataStream ds(message);
+ QByteArray command;
+ ds >> command;
+ if (command == "BREAKPOINTS") {
+ JSAgentBreakpoints breakpoints;
+ ds >> breakpoints;
+ m_agent->setBreakpoints(breakpoints);
+
+ //qDebug() << "BREAKPOINTS";
+ //foreach (const JSAgentBreakpointData &bp, breakpoints)
+ // qDebug() << "BREAKPOINT: " << bp.fileUrl << bp.lineNumber;
+ } else if (command == "WATCH_EXPRESSIONS") {
+ QStringList watchExpressions;
+ ds >> watchExpressions;
+ m_agent->setWatchExpressions(watchExpressions);
+ } else if (command == "STEPOVER") {
+ m_agent->stepOver();
+ } else if (command == "STEPINTO" || command == "INTERRUPT") {
+ m_agent->stepInto();
+ } else if (command == "STEPOUT") {
+ m_agent->stepOut();
+ } else if (command == "CONTINUE") {
+ m_agent->continueExecution();
+ } else if (command == "EXEC") {
+ QByteArray id;
+ QString expr;
+ ds >> id >> expr;
+
+ JSAgentWatchData data = m_agent->executeExpression(expr);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("RESULT") << id << data;
+ sendMessage(reply);
+ } else if (command == "EXPAND") {
+ QByteArray requestId;
+ quint64 objectId;
+ ds >> requestId >> objectId;
+
+ QList<JSAgentWatchData> result = m_agent->expandObjectById(objectId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("EXPANDED") << requestId << result;
+ sendMessage(reply);
+ } else if (command == "ACTIVATE_FRAME") {
+ int frameId;
+ ds >> frameId;
+
+ QList<JSAgentWatchData> locals = m_agent->localsAtFrame(frameId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("LOCALS") << frameId << locals;
+ sendMessage(reply);
+ } else if (command == "SET_PROPERTY") {
+ QByteArray id;
+ qint64 objectId;
+ QString property;
+ QString value;
+ ds >> id >> objectId >> property >> value;
+
+ m_agent->setProperty(objectId, property, value);
+
+ //TODO: feedback
+ } else if (command == "PING") {
+ int ping;
+ ds >> ping;
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("PONG") << ping;
+ sendMessage(reply);
+ } else if (command == "COVERAGE") {
+ bool enabled;
+ ds >> enabled;
+ m_agent->setCoverageEnabled(enabled);
+ if (!enabled) {
+ sendMessages();
+ }
+ } else {
+ qDebug() << Q_FUNC_INFO << "Unknown command" << command;
+ }
+
+ QDeclarativeDebugService::messageReceived(message);
+}
+
+void QJSDebugService::executionStopped(bool becauseOfException,
+ const QString &exception)
+{
+ const QList<JSAgentStackData> backtrace = m_agent->backtrace();
+ const QList<JSAgentWatchData> watches = m_agent->watches();
+ const QList<JSAgentWatchData> locals = m_agent->locals();
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("STOPPED") << backtrace << watches << locals
+ << becauseOfException << exception;
+ sendMessage(reply);
+}
+
+/*
+ Either send the message directly, or queue up
+ a list of messages to send later (via sendMessages)
+*/
+void QJSDebugService::processMessage(const JSAgentCoverageData &message)
+{
+ if (m_deferredSend)
+ m_data.append(message);
+ else
+ sendMessage(message.toByteArray());
+}
+
+/*
+ Send the messages queued up by processMessage
+*/
+void QJSDebugService::sendMessages()
+{
+ if (m_deferredSend) {
+ //### this is a suboptimal way to send batched messages
+ for (int i = 0; i < m_data.count(); ++i)
+ sendMessage(m_data.at(i).toByteArray());
+ m_data.clear();
+
+ //indicate completion
+ QByteArray data;
+ QDataStream ds(&data, QIODevice::WriteOnly);
+ ds << QByteArray("COVERAGE") << (qint64)-1 << (int)CoverageComplete;
+ sendMessage(data);
+ }
+}
+
diff --git a/src/declarative/debugger/qjsdebugservice_p.h b/src/declarative/debugger/qjsdebugservice_p.h
new file mode 100644
index 00000000..399b0fba
--- /dev/null
+++ b/src/declarative/debugger/qjsdebugservice_p.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QJSDEBUGSERVICE_P_H
+#define QJSDEBUGSERVICE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QPointer>
+#include <QElapsedTimer>
+
+#include "private/qdeclarativedebugservice_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeEngine;
+class QJSDebuggerAgent;
+
+struct JSAgentCoverageData
+{
+ QByteArray prefix;
+ qint64 time;
+ int messageType;
+
+ qint64 scriptId;
+ QString program;
+ QString fileName;
+ int baseLineNumber;
+ int lineNumber;
+ int columnNumber;
+ QString returnValue;
+
+ QByteArray toByteArray() const;
+};
+
+class QJSDebugService : public QDeclarativeDebugService
+{
+ Q_OBJECT
+
+public:
+ QJSDebugService(QObject *parent = 0);
+ ~QJSDebugService();
+
+ static QJSDebugService *instance();
+
+ void addEngine(QDeclarativeEngine *);
+ void removeEngine(QDeclarativeEngine *);
+ void processMessage(const JSAgentCoverageData &message);
+
+ QElapsedTimer m_timer;
+
+protected:
+ void statusChanged(Status status);
+ void messageReceived(const QByteArray &);
+
+private Q_SLOTS:
+ void executionStopped(bool becauseOfException,
+ const QString &exception);
+
+private:
+ void sendMessages();
+ QList<QDeclarativeEngine *> m_engines;
+ QPointer<QJSDebuggerAgent> m_agent;
+ bool m_deferredSend;
+ QList<JSAgentCoverageData> m_data;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QJSDEBUGSERVICE_P_H
diff --git a/src/declarative/debugger/qpacketprotocol.cpp b/src/declarative/debugger/qpacketprotocol.cpp
new file mode 100644
index 00000000..6732c850
--- /dev/null
+++ b/src/declarative/debugger/qpacketprotocol.cpp
@@ -0,0 +1,557 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qpacketprotocol_p.h"
+
+#include <QBuffer>
+#include <QElapsedTimer>
+
+QT_BEGIN_NAMESPACE
+
+#define MAX_PACKET_SIZE 0x7FFFFFFF
+
+/*!
+ \class QPacketProtocol
+ \internal
+
+ \brief The QPacketProtocol class encapsulates communicating discrete packets
+ across fragmented IO channels, such as TCP sockets.
+
+ QPacketProtocol makes it simple to send arbitrary sized data "packets" across
+ fragmented transports such as TCP and UDP.
+
+ As transmission boundaries are not respected, sending packets over protocols
+ like TCP frequently involves "stitching" them back together at the receiver.
+ QPacketProtocol makes this easier by performing this task for you. Packet
+ data sent using QPacketProtocol is prepended with a 4-byte size header
+ allowing the receiving QPacketProtocol to buffer the packet internally until
+ it has all been received. QPacketProtocol does not perform any sanity
+ checking on the size or on the data, so this class should only be used in
+ prototyping or trusted situations where DOS attacks are unlikely.
+
+ QPacketProtocol does not perform any communications itself. Instead it can
+ operate on any QIODevice that supports the QIODevice::readyRead() signal. A
+ logical "packet" is encapsulated by the companion QPacket class. The
+ following example shows two ways to send data using QPacketProtocol. The
+ transmitted data is equivalent in both.
+
+ \code
+ QTcpSocket socket;
+ // ... connect socket ...
+
+ QPacketProtocol protocol(&socket);
+
+ // Send packet the quick way
+ protocol.send() << "Hello world" << 123;
+
+ // Send packet the longer way
+ QPacket packet;
+ packet << "Hello world" << 123;
+ protocol.send(packet);
+ \endcode
+
+ Likewise, the following shows how to read data from QPacketProtocol, assuming
+ that the QPacketProtocol::readyRead() signal has been emitted.
+
+ \code
+ // ... QPacketProtocol::readyRead() is emitted ...
+
+ int a;
+ QByteArray b;
+
+ // Receive packet the quick way
+ protocol.read() >> a >> b;
+
+ // Receive packet the longer way
+ QPacket packet = protocol.read();
+ p >> a >> b;
+ \endcode
+
+ \ingroup io
+ \sa QPacket
+*/
+
+class QPacketProtocolPrivate : public QObject
+{
+Q_OBJECT
+public:
+ QPacketProtocolPrivate(QPacketProtocol * parent, QIODevice * _dev)
+ : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
+ waitingForPacket(false), dev(_dev)
+ {
+ Q_ASSERT(4 == sizeof(qint32));
+
+ QObject::connect(this, SIGNAL(readyRead()),
+ parent, SIGNAL(readyRead()));
+ QObject::connect(this, SIGNAL(packetWritten()),
+ parent, SIGNAL(packetWritten()));
+ QObject::connect(this, SIGNAL(invalidPacket()),
+ parent, SIGNAL(invalidPacket()));
+ QObject::connect(dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::connect(dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+ }
+
+Q_SIGNALS:
+ void readyRead();
+ void packetWritten();
+ void invalidPacket();
+
+public Q_SLOTS:
+ void aboutToClose()
+ {
+ inProgress.clear();
+ sendingPackets.clear();
+ inProgressSize = -1;
+ }
+
+ void bytesWritten(qint64 bytes)
+ {
+ Q_ASSERT(!sendingPackets.isEmpty());
+
+ while(bytes) {
+ if(sendingPackets.at(0) > bytes) {
+ sendingPackets[0] -= bytes;
+ bytes = 0;
+ } else {
+ bytes -= sendingPackets.at(0);
+ sendingPackets.removeFirst();
+ emit packetWritten();
+ }
+ }
+ }
+
+ void readyToRead()
+ {
+ bool gotPackets = false;
+ while (true) {
+ // Get size header (if not in progress)
+ if (-1 == inProgressSize) {
+ // We need a size header of sizeof(qint32)
+ if (sizeof(qint32) > (uint)dev->bytesAvailable()) {
+ if (gotPackets)
+ emit readyRead();
+ return; // no more data available
+ }
+
+ // Read size header
+ int read = dev->read((char *)&inProgressSize, sizeof(qint32));
+ Q_ASSERT(read == sizeof(qint32));
+ Q_UNUSED(read);
+
+ // Check sizing constraints
+ if (inProgressSize > maxPacketSize) {
+ QObject::disconnect(dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::disconnect(dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::disconnect(dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+ dev = 0;
+ emit invalidPacket();
+ return;
+ }
+
+ inProgressSize -= sizeof(qint32);
+ } else {
+ inProgress.append(dev->read(inProgressSize - inProgress.size()));
+
+ if (inProgressSize == inProgress.size()) {
+ // Packet has arrived!
+ packets.append(inProgress);
+ inProgressSize = -1;
+ inProgress.clear();
+
+ waitingForPacket = false;
+ gotPackets = true;
+ } else {
+ if (gotPackets)
+ emit readyRead();
+ return; // packet in progress is not yet complete
+ }
+ }
+ }
+ }
+
+public:
+ QList<qint64> sendingPackets;
+ QList<QByteArray> packets;
+ QByteArray inProgress;
+ qint32 inProgressSize;
+ qint32 maxPacketSize;
+ bool waitingForPacket;
+ QIODevice * dev;
+};
+
+/*!
+ Construct a QPacketProtocol instance that works on \a dev with the
+ specified \a parent.
+ */
+QPacketProtocol::QPacketProtocol(QIODevice * dev, QObject * parent)
+: QObject(parent), d(new QPacketProtocolPrivate(this, dev))
+{
+ Q_ASSERT(dev);
+}
+
+/*!
+ Destroys the QPacketProtocol instance.
+ */
+QPacketProtocol::~QPacketProtocol()
+{
+}
+
+/*!
+ Returns the maximum packet size allowed. By default this is
+ 2,147,483,647 bytes.
+
+ If a packet claiming to be larger than the maximum packet size is received,
+ the QPacketProtocol::invalidPacket() signal is emitted.
+
+ \sa QPacketProtocol::setMaximumPacketSize()
+ */
+qint32 QPacketProtocol::maximumPacketSize() const
+{
+ return d->maxPacketSize;
+}
+
+/*!
+ Sets the maximum allowable packet size to \a max.
+
+ \sa QPacketProtocol::maximumPacketSize()
+ */
+qint32 QPacketProtocol::setMaximumPacketSize(qint32 max)
+{
+ if(max > (signed)sizeof(qint32))
+ d->maxPacketSize = max;
+ return d->maxPacketSize;
+}
+
+/*!
+ Returns a streamable object that is transmitted on destruction. For example
+
+ \code
+ protocol.send() << "Hello world" << 123;
+ \endcode
+
+ will send a packet containing "Hello world" and 123. To construct more
+ complex packets, explicitly construct a QPacket instance.
+ */
+QPacketAutoSend QPacketProtocol::send()
+{
+ return QPacketAutoSend(this);
+}
+
+/*!
+ \fn void QPacketProtocol::send(const QPacket & packet)
+
+ Transmit the \a packet.
+ */
+void QPacketProtocol::send(const QPacket & p)
+{
+ if(p.b.isEmpty())
+ return; // We don't send empty packets
+
+ qint64 sendSize = p.b.size() + sizeof(qint32);
+
+ d->sendingPackets.append(sendSize);
+ qint32 sendSize32 = sendSize;
+ qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
+ Q_ASSERT(writeBytes == sizeof(qint32));
+ writeBytes = d->dev->write(p.b);
+ Q_ASSERT(writeBytes == p.b.size());
+}
+
+/*!
+ Returns the number of received packets yet to be read.
+ */
+qint64 QPacketProtocol::packetsAvailable() const
+{
+ return d->packets.count();
+}
+
+/*!
+ Discard any unread packets.
+ */
+void QPacketProtocol::clear()
+{
+ d->packets.clear();
+}
+
+/*!
+ Return the next unread packet, or an invalid QPacket instance if no packets
+ are available. This method does NOT block.
+ */
+QPacket QPacketProtocol::read()
+{
+ if(0 == d->packets.count())
+ return QPacket();
+
+ QPacket rv(d->packets.at(0));
+ d->packets.removeFirst();
+ return rv;
+}
+
+/*
+ Returns the difference between msecs and elapsed. If msecs is -1,
+ however, -1 is returned.
+*/
+static int qt_timeout_value(int msecs, int elapsed)
+{
+ if (msecs == -1)
+ return -1;
+
+ int timeout = msecs - elapsed;
+ return timeout < 0 ? 0 : timeout;
+}
+
+/*!
+ This function locks until a new packet is available for reading and the
+ \l{QIODevice::}{readyRead()} signal has been emitted. The function
+ will timeout after \a msecs milliseconds; the default timeout is
+ 30000 milliseconds.
+
+ The function returns true if the readyRead() signal is emitted and
+ there is new data available for reading; otherwise it returns false
+ (if an error occurred or the operation timed out).
+ */
+
+bool QPacketProtocol::waitForReadyRead(int msecs)
+{
+ if (!d->packets.isEmpty())
+ return true;
+
+ QElapsedTimer stopWatch;
+ stopWatch.start();
+
+ d->waitingForPacket = true;
+ do {
+ if (!d->dev->waitForReadyRead(msecs))
+ return false;
+ if (!d->waitingForPacket)
+ return true;
+ msecs = qt_timeout_value(msecs, stopWatch.elapsed());
+ } while (true);
+}
+
+/*!
+ Return the QIODevice passed to the QPacketProtocol constructor.
+*/
+QIODevice * QPacketProtocol::device()
+{
+ return d->dev;
+}
+
+/*!
+ \fn void QPacketProtocol::readyRead()
+
+ Emitted whenever a new packet is received. Applications may use
+ QPacketProtocol::read() to retrieve this packet.
+ */
+
+/*!
+ \fn void QPacketProtocol::invalidPacket()
+
+ A packet larger than the maximum allowable packet size was received. The
+ packet will be discarded and, as it indicates corruption in the protocol, no
+ further packets will be received.
+ */
+
+/*!
+ \fn void QPacketProtocol::packetWritten()
+
+ Emitted each time a packet is completing written to the device. This signal
+ may be used for communications flow control.
+ */
+
+/*!
+ \class QPacket
+ \internal
+
+ \brief The QPacket class encapsulates an unfragmentable packet of data to be
+ transmitted by QPacketProtocol.
+
+ The QPacket class works together with QPacketProtocol to make it simple to
+ send arbitrary sized data "packets" across fragmented transports such as TCP
+ and UDP.
+
+ QPacket provides a QDataStream interface to an unfragmentable packet.
+ Applications should construct a QPacket, propagate it with data and then
+ transmit it over a QPacketProtocol instance. For example:
+ \code
+ QPacketProtocol protocol(...);
+
+ QPacket myPacket;
+ myPacket << "Hello world!" << 123;
+ protocol.send(myPacket);
+ \endcode
+
+ As long as both ends of the connection are using the QPacketProtocol class,
+ the data within this packet will be delivered unfragmented at the other end,
+ ready for extraction.
+
+ \code
+ QByteArray greeting;
+ int count;
+
+ QPacket myPacket = protocol.read();
+
+ myPacket >> greeting >> count;
+ \endcode
+
+ Only packets returned from QPacketProtocol::read() may be read from. QPacket
+ instances constructed by directly by applications are for transmission only
+ and are considered "write only". Attempting to read data from them will
+ result in undefined behavior.
+
+ \ingroup io
+ \sa QPacketProtocol
+ */
+
+/*!
+ Constructs an empty write-only packet.
+ */
+QPacket::QPacket()
+: QDataStream(), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(QIODevice::WriteOnly);
+ setDevice(buf);
+ setVersion(QDataStream::Qt_4_7);
+}
+
+/*!
+ Destroys the QPacket instance.
+ */
+QPacket::~QPacket()
+{
+ if(buf) {
+ delete buf;
+ buf = 0;
+ }
+}
+
+/*!
+ Creates a copy of \a other. The initial stream positions are shared, but the
+ two packets are otherwise independent.
+ */
+QPacket::QPacket(const QPacket & other)
+: QDataStream(), b(other.b), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(other.buf->openMode());
+ setDevice(buf);
+}
+
+/*!
+ \internal
+ */
+QPacket::QPacket(const QByteArray & ba)
+: QDataStream(), b(ba), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(QIODevice::ReadOnly);
+ setDevice(buf);
+}
+
+/*!
+ Returns true if this packet is empty - that is, contains no data.
+ */
+bool QPacket::isEmpty() const
+{
+ return b.isEmpty();
+}
+
+/*!
+ Returns raw packet data.
+ */
+QByteArray QPacket::data() const
+{
+ return b;
+}
+
+/*!
+ Clears data in the packet. This is useful for reusing one writable packet.
+ For example
+ \code
+ QPacketProtocol protocol(...);
+
+ QPacket packet;
+
+ packet << "Hello world!" << 123;
+ protocol.send(packet);
+
+ packet.clear();
+ packet << "Goodbyte world!" << 789;
+ protocol.send(packet);
+ \endcode
+ */
+void QPacket::clear()
+{
+ QBuffer::OpenMode oldMode = buf->openMode();
+ buf->close();
+ b.clear();
+ buf->setBuffer(&b); // reset QBuffer internals with new size of b.
+ buf->open(oldMode);
+}
+
+/*!
+ \class QPacketAutoSend
+ \internal
+
+ \internal
+ */
+QPacketAutoSend::QPacketAutoSend(QPacketProtocol * _p)
+: QPacket(), p(_p)
+{
+}
+
+QPacketAutoSend::~QPacketAutoSend()
+{
+ if(!b.isEmpty())
+ p->send(*this);
+}
+
+QT_END_NAMESPACE
+
+#include <qpacketprotocol.moc>
diff --git a/src/declarative/debugger/qpacketprotocol_p.h b/src/declarative/debugger/qpacketprotocol_p.h
new file mode 100644
index 00000000..62dedf4d
--- /dev/null
+++ b/src/declarative/debugger/qpacketprotocol_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPACKETPROTOCOL_H
+#define QPACKETPROTOCOL_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qdatastream.h>
+
+#include <private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QIODevice;
+class QBuffer;
+class QPacket;
+class QPacketAutoSend;
+class QPacketProtocolPrivate;
+
+class Q_DECLARATIVE_EXPORT QPacketProtocol : public QObject
+{
+Q_OBJECT
+public:
+ explicit QPacketProtocol(QIODevice * dev, QObject * parent = 0);
+ virtual ~QPacketProtocol();
+
+ qint32 maximumPacketSize() const;
+ qint32 setMaximumPacketSize(qint32);
+
+ QPacketAutoSend send();
+ void send(const QPacket &);
+
+ qint64 packetsAvailable() const;
+ QPacket read();
+
+ bool waitForReadyRead(int msecs = 3000);
+
+ void clear();
+
+ QIODevice * device();
+
+Q_SIGNALS:
+ void readyRead();
+ void invalidPacket();
+ void packetWritten();
+
+private:
+ QPacketProtocolPrivate * d;
+};
+
+
+class Q_DECLARATIVE_EXPORT QPacket : public QDataStream
+{
+public:
+ QPacket();
+ QPacket(const QPacket &);
+ virtual ~QPacket();
+
+ void clear();
+ bool isEmpty() const;
+ QByteArray data() const;
+
+protected:
+ friend class QPacketProtocol;
+ QPacket(const QByteArray & ba);
+ QByteArray b;
+ QBuffer * buf;
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QPacketAutoSend : public QPacket
+{
+public:
+ virtual ~QPacketAutoSend();
+
+private:
+ friend class QPacketProtocol;
+ QPacketAutoSend(QPacketProtocol *);
+ QPacketProtocol * p;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro
new file mode 100644
index 00000000..055e4b93
--- /dev/null
+++ b/src/declarative/declarative.pro
@@ -0,0 +1,43 @@
+TARGET = QtDeclarative
+QPRO_PWD = $$PWD
+QT = core gui script network
+contains(QT_CONFIG, svg): QT += svg
+DEFINES += QT_BUILD_DECLARATIVE_LIB QT_NO_URL_CAST_FROM_STRING
+win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x66000000
+solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
+
+unix|win32-g++*:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui
+
+exists("qdeclarative_enable_gcov") {
+ QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors
+ LIBS += -lgcov
+}
+
+include(../qbase.pri)
+
+#INCLUDEPATH -= $$QMAKE_INCDIR_QT/$$TARGET
+#DESTDIR=.
+
+#modules
+include(util/util.pri)
+include(graphicsitems/graphicsitems.pri)
+include(qml/qml.pri)
+include(debugger/debugger.pri)
+
+symbian: {
+ TARGET.UID3=0x2001E623
+ LIBS += -lefsrv -lhal
+
+ contains(QT_CONFIG, freetype) {
+ DEFINES += QT_NO_FONTCONFIG
+ INCLUDEPATH += \
+ ../3rdparty/freetype/src \
+ ../3rdparty/freetype/include
+ }
+}
+
+linux-g++-maemo:DEFINES += QDECLARATIVEVIEW_NOBACKGROUND
+
+DEFINES += QT_NO_OPENTYPE
+INCLUDEPATH += ../3rdparty/harfbuzz/src
+
diff --git a/src/declarative/graphicsitems/graphicsitems.pri b/src/declarative/graphicsitems/graphicsitems.pri
new file mode 100644
index 00000000..99042740
--- /dev/null
+++ b/src/declarative/graphicsitems/graphicsitems.pri
@@ -0,0 +1,94 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qdeclarativeitemsmodule_p.h \
+ $$PWD/qdeclarativeanchors_p.h \
+ $$PWD/qdeclarativeanchors_p_p.h \
+ $$PWD/qdeclarativeevents_p_p.h \
+ $$PWD/qdeclarativeflickable_p.h \
+ $$PWD/qdeclarativeflickable_p_p.h \
+ $$PWD/qdeclarativeflipable_p.h \
+ $$PWD/qdeclarativegridview_p.h \
+ $$PWD/qdeclarativeimage_p.h \
+ $$PWD/qdeclarativeimagebase_p.h \
+ $$PWD/qdeclarativeborderimage_p.h \
+ $$PWD/qdeclarativepainteditem_p.h \
+ $$PWD/qdeclarativepainteditem_p_p.h \
+ $$PWD/qdeclarativeimage_p_p.h \
+ $$PWD/qdeclarativeborderimage_p_p.h \
+ $$PWD/qdeclarativeimagebase_p_p.h \
+ $$PWD/qdeclarativeanimatedimage_p.h \
+ $$PWD/qdeclarativeanimatedimage_p_p.h \
+ $$PWD/qdeclarativeitem.h \
+ $$PWD/qdeclarativeitem_p.h \
+ $$PWD/qdeclarativefocuspanel_p.h \
+ $$PWD/qdeclarativefocusscope_p.h \
+ $$PWD/qdeclarativepositioners_p.h \
+ $$PWD/qdeclarativepositioners_p_p.h \
+ $$PWD/qdeclarativeloader_p.h \
+ $$PWD/qdeclarativeloader_p_p.h \
+ $$PWD/qdeclarativemousearea_p.h \
+ $$PWD/qdeclarativemousearea_p_p.h \
+ $$PWD/qdeclarativepath_p.h \
+ $$PWD/qdeclarativepath_p_p.h \
+ $$PWD/qdeclarativepathview_p.h \
+ $$PWD/qdeclarativepathview_p_p.h \
+ $$PWD/qdeclarativerectangle_p.h \
+ $$PWD/qdeclarativerectangle_p_p.h \
+ $$PWD/qdeclarativerepeater_p.h \
+ $$PWD/qdeclarativerepeater_p_p.h \
+ $$PWD/qdeclarativescalegrid_p_p.h \
+ $$PWD/qdeclarativetranslate_p.h \
+ $$PWD/qdeclarativetextinput_p.h \
+ $$PWD/qdeclarativetextinput_p_p.h \
+ $$PWD/qdeclarativetextedit_p.h \
+ $$PWD/qdeclarativetextedit_p_p.h \
+ $$PWD/qdeclarativetext_p.h \
+ $$PWD/qdeclarativetext_p_p.h \
+ $$PWD/qdeclarativevisualitemmodel_p.h \
+ $$PWD/qdeclarativelistview_p.h \
+ $$PWD/qdeclarativelayoutitem_p.h \
+ $$PWD/qdeclarativeitemchangelistener_p.h \
+ $$PWD/qdeclarativegraphicswidget_p.h \
+ $$PWD/qdeclarativetextlayout_p.h \
+ $$PWD/qdeclarativepincharea_p.h \
+ $$PWD/qdeclarativepincharea_p_p.h \
+ $$PWD/qdeclarativeimplicitsizeitem_p.h \
+ $$PWD/qdeclarativeimplicitsizeitem_p_p.h
+
+
+SOURCES += \
+ $$PWD/qdeclarativeitemsmodule.cpp \
+ $$PWD/qdeclarativeanchors.cpp \
+ $$PWD/qdeclarativeevents.cpp \
+ $$PWD/qdeclarativeflickable.cpp \
+ $$PWD/qdeclarativeflipable.cpp \
+ $$PWD/qdeclarativegridview.cpp \
+ $$PWD/qdeclarativeimage.cpp \
+ $$PWD/qdeclarativeborderimage.cpp \
+ $$PWD/qdeclarativeimagebase.cpp \
+ $$PWD/qdeclarativeanimatedimage.cpp \
+ $$PWD/qdeclarativepainteditem.cpp \
+ $$PWD/qdeclarativeitem.cpp \
+ $$PWD/qdeclarativefocuspanel.cpp \
+ $$PWD/qdeclarativefocusscope.cpp \
+ $$PWD/qdeclarativepositioners.cpp \
+ $$PWD/qdeclarativeloader.cpp \
+ $$PWD/qdeclarativemousearea.cpp \
+ $$PWD/qdeclarativepath.cpp \
+ $$PWD/qdeclarativepathview.cpp \
+ $$PWD/qdeclarativerectangle.cpp \
+ $$PWD/qdeclarativerepeater.cpp \
+ $$PWD/qdeclarativescalegrid.cpp \
+ $$PWD/qdeclarativetranslate.cpp \
+ $$PWD/qdeclarativetextinput.cpp \
+ $$PWD/qdeclarativetext.cpp \
+ $$PWD/qdeclarativetextedit.cpp \
+ $$PWD/qdeclarativevisualitemmodel.cpp \
+ $$PWD/qdeclarativelistview.cpp \
+ $$PWD/qdeclarativelayoutitem.cpp \
+ $$PWD/qdeclarativegraphicswidget.cpp \
+ $$PWD/qdeclarativetextlayout.cpp \
+ $$PWD/qdeclarativepincharea.cpp \
+ $$PWD/qdeclarativeimplicitsizeitem.cpp
+
diff --git a/src/declarative/graphicsitems/qdeclarativeanchors.cpp b/src/declarative/graphicsitems/qdeclarativeanchors.cpp
new file mode 100644
index 00000000..f8ca54cb
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeanchors.cpp
@@ -0,0 +1,1165 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativeanchors_p_p.h"
+
+#include "qdeclarativeitem.h"
+#include "private/qdeclarativeitem_p.h"
+
+#include <qdeclarativeinfo.h>
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+//TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
+//TODO: support non-parent, non-sibling (need to find lowest common ancestor)
+
+static qreal hcenter(QGraphicsItem *i)
+{
+ QGraphicsItemPrivate *item = QGraphicsItemPrivate::get(i);
+
+ qreal width = item->width();
+ int iw = width;
+ if (iw % 2)
+ return (width + 1) / 2;
+ else
+ return width / 2;
+}
+
+static qreal vcenter(QGraphicsItem *i)
+{
+ QGraphicsItemPrivate *item = QGraphicsItemPrivate::get(i);
+
+ qreal height = item->height();
+ int ih = height;
+ if (ih % 2)
+ return (height + 1) / 2;
+ else
+ return height / 2;
+}
+
+//### const item?
+//local position
+static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
+{
+ qreal ret = 0.0;
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item);
+ switch(anchorLine) {
+ case QDeclarativeAnchorLine::Left:
+ ret = item->x();
+ break;
+ case QDeclarativeAnchorLine::Right:
+ ret = item->x() + d->width();
+ break;
+ case QDeclarativeAnchorLine::Top:
+ ret = item->y();
+ break;
+ case QDeclarativeAnchorLine::Bottom:
+ ret = item->y() + d->height();
+ break;
+ case QDeclarativeAnchorLine::HCenter:
+ ret = item->x() + hcenter(item);
+ break;
+ case QDeclarativeAnchorLine::VCenter:
+ ret = item->y() + vcenter(item);
+ break;
+ case QDeclarativeAnchorLine::Baseline:
+ if (d->isDeclarativeItem)
+ ret = item->y() + static_cast<QDeclarativeItem*>(item)->baselineOffset();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+//position when origin is 0,0
+static qreal adjustedPosition(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
+{
+ qreal ret = 0.0;
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item);
+ switch(anchorLine) {
+ case QDeclarativeAnchorLine::Left:
+ ret = 0.0;
+ break;
+ case QDeclarativeAnchorLine::Right:
+ ret = d->width();
+ break;
+ case QDeclarativeAnchorLine::Top:
+ ret = 0.0;
+ break;
+ case QDeclarativeAnchorLine::Bottom:
+ ret = d->height();
+ break;
+ case QDeclarativeAnchorLine::HCenter:
+ ret = hcenter(item);
+ break;
+ case QDeclarativeAnchorLine::VCenter:
+ ret = vcenter(item);
+ break;
+ case QDeclarativeAnchorLine::Baseline:
+ if (d->isDeclarativeItem)
+ ret = static_cast<QDeclarativeItem*>(item)->baselineOffset();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+QDeclarativeAnchors::QDeclarativeAnchors(QObject *parent)
+ : QObject(*new QDeclarativeAnchorsPrivate(0), parent)
+{
+ qFatal("QDeclarativeAnchors::QDeclarativeAnchors(QObject*) called");
+}
+
+QDeclarativeAnchors::QDeclarativeAnchors(QGraphicsObject *item, QObject *parent)
+ : QObject(*new QDeclarativeAnchorsPrivate(item), parent)
+{
+}
+
+QDeclarativeAnchors::~QDeclarativeAnchors()
+{
+ Q_D(QDeclarativeAnchors);
+ d->remDepend(d->fill);
+ d->remDepend(d->centerIn);
+ d->remDepend(d->left.item);
+ d->remDepend(d->right.item);
+ d->remDepend(d->top.item);
+ d->remDepend(d->bottom.item);
+ d->remDepend(d->vCenter.item);
+ d->remDepend(d->hCenter.item);
+ d->remDepend(d->baseline.item);
+}
+
+void QDeclarativeAnchorsPrivate::fillChanged()
+{
+ Q_Q(QDeclarativeAnchors);
+ if (!fill || !isItemComplete())
+ return;
+
+ if (updatingFill < 2) {
+ ++updatingFill;
+
+ qreal horizontalMargin = q->mirrored() ? rightMargin : leftMargin;
+
+ if (fill == item->parentItem()) { //child-parent
+ setItemPos(QPointF(horizontalMargin, topMargin));
+ } else if (fill->parentItem() == item->parentItem()) { //siblings
+ setItemPos(QPointF(fill->x()+horizontalMargin, fill->y()+topMargin));
+ }
+ QGraphicsItemPrivate *fillPrivate = QGraphicsItemPrivate::get(fill);
+ setItemSize(QSizeF(fillPrivate->width()-leftMargin-rightMargin, fillPrivate->height()-topMargin-bottomMargin));
+
+ --updatingFill;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on fill.");
+ }
+
+}
+
+void QDeclarativeAnchorsPrivate::centerInChanged()
+{
+ Q_Q(QDeclarativeAnchors);
+ if (!centerIn || fill || !isItemComplete())
+ return;
+
+ if (updatingCenterIn < 2) {
+ ++updatingCenterIn;
+
+ qreal effectiveHCenterOffset = q->mirrored() ? -hCenterOffset : hCenterOffset;
+ if (centerIn == item->parentItem()) {
+ QPointF p(hcenter(item->parentItem()) - hcenter(item) + effectiveHCenterOffset,
+ vcenter(item->parentItem()) - vcenter(item) + vCenterOffset);
+ setItemPos(p);
+
+ } else if (centerIn->parentItem() == item->parentItem()) {
+ QPointF p(centerIn->x() + hcenter(centerIn) - hcenter(item) + effectiveHCenterOffset,
+ centerIn->y() + vcenter(centerIn) - vcenter(item) + vCenterOffset);
+ setItemPos(p);
+ }
+
+ --updatingCenterIn;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on centerIn.");
+ }
+}
+
+void QDeclarativeAnchorsPrivate::clearItem(QGraphicsObject *item)
+{
+ if (!item)
+ return;
+ if (fill == item)
+ fill = 0;
+ if (centerIn == item)
+ centerIn = 0;
+ if (left.item == item) {
+ left.item = 0;
+ usedAnchors &= ~QDeclarativeAnchors::LeftAnchor;
+ }
+ if (right.item == item) {
+ right.item = 0;
+ usedAnchors &= ~QDeclarativeAnchors::RightAnchor;
+ }
+ if (top.item == item) {
+ top.item = 0;
+ usedAnchors &= ~QDeclarativeAnchors::TopAnchor;
+ }
+ if (bottom.item == item) {
+ bottom.item = 0;
+ usedAnchors &= ~QDeclarativeAnchors::BottomAnchor;
+ }
+ if (vCenter.item == item) {
+ vCenter.item = 0;
+ usedAnchors &= ~QDeclarativeAnchors::VCenterAnchor;
+ }
+ if (hCenter.item == item) {
+ hCenter.item = 0;
+ usedAnchors &= ~QDeclarativeAnchors::HCenterAnchor;
+ }
+ if (baseline.item == item) {
+ baseline.item = 0;
+ usedAnchors &= ~QDeclarativeAnchors::BaselineAnchor;
+ }
+}
+
+void QDeclarativeAnchorsPrivate::addDepend(QGraphicsObject *item)
+{
+ if (!item)
+ return;
+ QGraphicsItemPrivate * itemPrivate = QGraphicsItemPrivate::get(item);
+ if (itemPrivate->isDeclarativeItem) {
+ QDeclarativeItemPrivate *p =
+ static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(item));
+ p->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ } else if(itemPrivate->isWidget) {
+ Q_Q(QDeclarativeAnchors);
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
+ QObject::connect(widget, SIGNAL(destroyed(QObject*)), q, SLOT(_q_widgetDestroyed(QObject*)));
+ QObject::connect(widget, SIGNAL(geometryChanged()), q, SLOT(_q_widgetGeometryChanged()));
+ }
+}
+
+void QDeclarativeAnchorsPrivate::remDepend(QGraphicsObject *item)
+{
+ if (!item)
+ return;
+ QGraphicsItemPrivate * itemPrivate = QGraphicsItemPrivate::get(item);
+ if (itemPrivate->isDeclarativeItem) {
+ QDeclarativeItemPrivate *p =
+ static_cast<QDeclarativeItemPrivate *>(itemPrivate);
+ p->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ } else if(itemPrivate->isWidget) {
+ Q_Q(QDeclarativeAnchors);
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
+ QObject::disconnect(widget, SIGNAL(destroyed(QObject*)), q, SLOT(_q_widgetDestroyed(QObject*)));
+ QObject::disconnect(widget, SIGNAL(geometryChanged()), q, SLOT(_q_widgetGeometryChanged()));
+ }
+}
+
+bool QDeclarativeAnchorsPrivate::isItemComplete() const
+{
+ return componentComplete;
+}
+
+void QDeclarativeAnchors::classBegin()
+{
+ Q_D(QDeclarativeAnchors);
+ d->componentComplete = false;
+}
+
+void QDeclarativeAnchors::componentComplete()
+{
+ Q_D(QDeclarativeAnchors);
+ d->componentComplete = true;
+}
+
+bool QDeclarativeAnchors::mirrored()
+{
+ Q_D(QDeclarativeAnchors);
+ QGraphicsItemPrivate * itemPrivate = QGraphicsItemPrivate::get(d->item);
+ return itemPrivate->isDeclarativeItem ? static_cast<QDeclarativeItemPrivate *>(itemPrivate)->effectiveLayoutMirror : false;
+}
+
+void QDeclarativeAnchorsPrivate::setItemHeight(qreal v)
+{
+ updatingMe = true;
+ QGraphicsItemPrivate::get(item)->setHeight(v);
+ updatingMe = false;
+}
+
+void QDeclarativeAnchorsPrivate::setItemWidth(qreal v)
+{
+ updatingMe = true;
+ QGraphicsItemPrivate::get(item)->setWidth(v);
+ updatingMe = false;
+}
+
+void QDeclarativeAnchorsPrivate::setItemX(qreal v)
+{
+ updatingMe = true;
+ item->setX(v);
+ updatingMe = false;
+}
+
+void QDeclarativeAnchorsPrivate::setItemY(qreal v)
+{
+ updatingMe = true;
+ item->setY(v);
+ updatingMe = false;
+}
+
+void QDeclarativeAnchorsPrivate::setItemPos(const QPointF &v)
+{
+ updatingMe = true;
+ item->setPos(v);
+ updatingMe = false;
+}
+
+void QDeclarativeAnchorsPrivate::setItemSize(const QSizeF &v)
+{
+ updatingMe = true;
+ if(QGraphicsItemPrivate::get(item)->isWidget)
+ static_cast<QGraphicsWidget *>(item)->resize(v);
+ else if (QGraphicsItemPrivate::get(item)->isDeclarativeItem)
+ static_cast<QDeclarativeItem *>(item)->setSize(v);
+ updatingMe = false;
+}
+
+void QDeclarativeAnchorsPrivate::updateMe()
+{
+ if (updatingMe) {
+ updatingMe = false;
+ return;
+ }
+
+ fillChanged();
+ centerInChanged();
+ updateHorizontalAnchors();
+ updateVerticalAnchors();
+}
+
+void QDeclarativeAnchorsPrivate::updateOnComplete()
+{
+ fillChanged();
+ centerInChanged();
+ updateHorizontalAnchors();
+ updateVerticalAnchors();
+}
+
+void QDeclarativeAnchorsPrivate::_q_widgetDestroyed(QObject *obj)
+{
+ clearItem(qobject_cast<QGraphicsObject*>(obj));
+}
+
+void QDeclarativeAnchorsPrivate::_q_widgetGeometryChanged()
+{
+ fillChanged();
+ centerInChanged();
+ updateHorizontalAnchors();
+ updateVerticalAnchors();
+}
+
+void QDeclarativeAnchorsPrivate::itemGeometryChanged(QDeclarativeItem *, const QRectF &newG, const QRectF &oldG)
+{
+ fillChanged();
+ centerInChanged();
+ if (newG.x() != oldG.x() || newG.width() != oldG.width())
+ updateHorizontalAnchors();
+ if (newG.y() != oldG.y() || newG.height() != oldG.height())
+ updateVerticalAnchors();
+}
+
+QGraphicsObject *QDeclarativeAnchors::fill() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->fill;
+}
+
+void QDeclarativeAnchors::setFill(QGraphicsObject *f)
+{
+ Q_D(QDeclarativeAnchors);
+ if (d->fill == f)
+ return;
+
+ if (!f) {
+ d->remDepend(d->fill);
+ d->fill = f;
+ emit fillChanged();
+ return;
+ }
+ if (f != d->item->parentItem() && f->parentItem() != d->item->parentItem()){
+ qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
+ return;
+ }
+ d->remDepend(d->fill);
+ d->fill = f;
+ d->addDepend(d->fill);
+ emit fillChanged();
+ d->fillChanged();
+}
+
+void QDeclarativeAnchors::resetFill()
+{
+ setFill(0);
+}
+
+QGraphicsObject *QDeclarativeAnchors::centerIn() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->centerIn;
+}
+
+void QDeclarativeAnchors::setCenterIn(QGraphicsObject* c)
+{
+ Q_D(QDeclarativeAnchors);
+ if (d->centerIn == c)
+ return;
+
+ if (!c) {
+ d->remDepend(d->centerIn);
+ d->centerIn = c;
+ emit centerInChanged();
+ return;
+ }
+ if (c != d->item->parentItem() && c->parentItem() != d->item->parentItem()){
+ qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
+ return;
+ }
+
+ d->remDepend(d->centerIn);
+ d->centerIn = c;
+ d->addDepend(d->centerIn);
+ emit centerInChanged();
+ d->centerInChanged();
+}
+
+void QDeclarativeAnchors::resetCenterIn()
+{
+ setCenterIn(0);
+}
+
+bool QDeclarativeAnchorsPrivate::calcStretch(const QDeclarativeAnchorLine &edge1,
+ const QDeclarativeAnchorLine &edge2,
+ qreal offset1,
+ qreal offset2,
+ QDeclarativeAnchorLine::AnchorLine line,
+ qreal &stretch)
+{
+ bool edge1IsParent = (edge1.item == item->parentItem());
+ bool edge2IsParent = (edge2.item == item->parentItem());
+ bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem());
+ bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem());
+
+ bool invalid = false;
+ if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
+ stretch = (position(edge2.item, edge2.anchorLine) + offset2)
+ - (position(edge1.item, edge1.anchorLine) + offset1);
+ } else if (edge2IsParent && edge1IsSibling) {
+ stretch = (position(edge2.item, edge2.anchorLine) + offset2)
+ - (position(item->parentObject(), line)
+ + position(edge1.item, edge1.anchorLine) + offset1);
+ } else if (edge2IsSibling && edge1IsParent) {
+ stretch = (position(item->parentObject(), line) + position(edge2.item, edge2.anchorLine) + offset2)
+ - (position(edge1.item, edge1.anchorLine) + offset1);
+ } else
+ invalid = true;
+
+ return invalid;
+}
+
+void QDeclarativeAnchorsPrivate::updateVerticalAnchors()
+{
+ if (fill || centerIn || !isItemComplete())
+ return;
+
+ if (updatingVerticalAnchor < 2) {
+ ++updatingVerticalAnchor;
+ QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item);
+ if (usedAnchors & QDeclarativeAnchors::TopAnchor) {
+ //Handle stretching
+ bool invalid = true;
+ qreal height = 0.0;
+ if (usedAnchors & QDeclarativeAnchors::BottomAnchor) {
+ invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QDeclarativeAnchorLine::Top, height);
+ } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) {
+ invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QDeclarativeAnchorLine::Top, height);
+ height *= 2;
+ }
+ if (!invalid)
+ setItemHeight(height);
+
+ //Handle top
+ if (top.item == item->parentItem()) {
+ setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin);
+ } else if (top.item->parentItem() == item->parentItem()) {
+ setItemY(position(top.item, top.anchorLine) + topMargin);
+ }
+ } else if (usedAnchors & QDeclarativeAnchors::BottomAnchor) {
+ //Handle stretching (top + bottom case is handled above)
+ if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) {
+ qreal height = 0.0;
+ bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin,
+ QDeclarativeAnchorLine::Top, height);
+ if (!invalid)
+ setItemHeight(height*2);
+ }
+
+ //Handle bottom
+ if (bottom.item == item->parentItem()) {
+ setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - itemPrivate->height() - bottomMargin);
+ } else if (bottom.item->parentItem() == item->parentItem()) {
+ setItemY(position(bottom.item, bottom.anchorLine) - itemPrivate->height() - bottomMargin);
+ }
+ } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) {
+ //(stetching handled above)
+
+ //Handle vCenter
+ if (vCenter.item == item->parentItem()) {
+ setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine)
+ - vcenter(item) + vCenterOffset);
+ } else if (vCenter.item->parentItem() == item->parentItem()) {
+ setItemY(position(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset);
+ }
+ } else if (usedAnchors & QDeclarativeAnchors::BaselineAnchor) {
+ //Handle baseline
+ if (baseline.item == item->parentItem()) {
+ if (itemPrivate->isDeclarativeItem)
+ setItemY(adjustedPosition(baseline.item, baseline.anchorLine)
+ - static_cast<QDeclarativeItem *>(item)->baselineOffset() + baselineOffset);
+ } else if (baseline.item->parentItem() == item->parentItem()) {
+ if (itemPrivate->isDeclarativeItem)
+ setItemY(position(baseline.item, baseline.anchorLine)
+ - static_cast<QDeclarativeItem *>(item)->baselineOffset() + baselineOffset);
+ }
+ }
+ --updatingVerticalAnchor;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on vertical anchor.");
+ }
+}
+
+inline QDeclarativeAnchorLine::AnchorLine reverseAnchorLine(QDeclarativeAnchorLine::AnchorLine anchorLine) {
+ if (anchorLine == QDeclarativeAnchorLine::Left) {
+ return QDeclarativeAnchorLine::Right;
+ } else if (anchorLine == QDeclarativeAnchorLine::Right) {
+ return QDeclarativeAnchorLine::Left;
+ } else {
+ return anchorLine;
+ }
+}
+
+void QDeclarativeAnchorsPrivate::updateHorizontalAnchors()
+{
+ Q_Q(QDeclarativeAnchors);
+ if (fill || centerIn || !isItemComplete())
+ return;
+
+ if (updatingHorizontalAnchor < 3) {
+ ++updatingHorizontalAnchor;
+ qreal effectiveRightMargin, effectiveLeftMargin, effectiveHorizontalCenterOffset;
+ QDeclarativeAnchorLine effectiveLeft, effectiveRight, effectiveHorizontalCenter;
+ QDeclarativeAnchors::Anchor effectiveLeftAnchor, effectiveRightAnchor;
+ if (q->mirrored()) {
+ effectiveLeftAnchor = QDeclarativeAnchors::RightAnchor;
+ effectiveRightAnchor = QDeclarativeAnchors::LeftAnchor;
+ effectiveLeft.item = right.item;
+ effectiveLeft.anchorLine = reverseAnchorLine(right.anchorLine);
+ effectiveRight.item = left.item;
+ effectiveRight.anchorLine = reverseAnchorLine(left.anchorLine);
+ effectiveHorizontalCenter.item = hCenter.item;
+ effectiveHorizontalCenter.anchorLine = reverseAnchorLine(hCenter.anchorLine);
+ effectiveLeftMargin = rightMargin;
+ effectiveRightMargin = leftMargin;
+ effectiveHorizontalCenterOffset = -hCenterOffset;
+ } else {
+ effectiveLeftAnchor = QDeclarativeAnchors::LeftAnchor;
+ effectiveRightAnchor = QDeclarativeAnchors::RightAnchor;
+ effectiveLeft = left;
+ effectiveRight = right;
+ effectiveHorizontalCenter = hCenter;
+ effectiveLeftMargin = leftMargin;
+ effectiveRightMargin = rightMargin;
+ effectiveHorizontalCenterOffset = hCenterOffset;
+ }
+
+ QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item);
+ if (usedAnchors & effectiveLeftAnchor) {
+ //Handle stretching
+ bool invalid = true;
+ qreal width = 0.0;
+ if (usedAnchors & effectiveRightAnchor) {
+ invalid = calcStretch(effectiveLeft, effectiveRight, effectiveLeftMargin, -effectiveRightMargin, QDeclarativeAnchorLine::Left, width);
+ } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
+ invalid = calcStretch(effectiveLeft, effectiveHorizontalCenter, effectiveLeftMargin, effectiveHorizontalCenterOffset, QDeclarativeAnchorLine::Left, width);
+ width *= 2;
+ }
+ if (!invalid)
+ setItemWidth(width);
+
+ //Handle left
+ if (effectiveLeft.item == item->parentItem()) {
+ setItemX(adjustedPosition(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin);
+ } else if (effectiveLeft.item->parentItem() == item->parentItem()) {
+ setItemX(position(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin);
+ }
+ } else if (usedAnchors & effectiveRightAnchor) {
+ //Handle stretching (left + right case is handled in updateLeftAnchor)
+ if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
+ qreal width = 0.0;
+ bool invalid = calcStretch(effectiveHorizontalCenter, effectiveRight, effectiveHorizontalCenterOffset, -effectiveRightMargin,
+ QDeclarativeAnchorLine::Left, width);
+ if (!invalid)
+ setItemWidth(width*2);
+ }
+
+ //Handle right
+ if (effectiveRight.item == item->parentItem()) {
+ setItemX(adjustedPosition(effectiveRight.item, effectiveRight.anchorLine) - itemPrivate->width() - effectiveRightMargin);
+ } else if (effectiveRight.item->parentItem() == item->parentItem()) {
+ setItemX(position(effectiveRight.item, effectiveRight.anchorLine) - itemPrivate->width() - effectiveRightMargin);
+ }
+ } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
+ //Handle hCenter
+ if (effectiveHorizontalCenter.item == item->parentItem()) {
+ setItemX(adjustedPosition(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset);
+ } else if (effectiveHorizontalCenter.item->parentItem() == item->parentItem()) {
+ setItemX(position(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset);
+ }
+ }
+ --updatingHorizontalAnchor;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on horizontal anchor.");
+ }
+}
+
+QDeclarativeAnchorLine QDeclarativeAnchors::top() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->top;
+}
+
+void QDeclarativeAnchors::setTop(const QDeclarativeAnchorLine &edge)
+{
+ Q_D(QDeclarativeAnchors);
+ if (!d->checkVAnchorValid(edge) || d->top == edge)
+ return;
+
+ d->usedAnchors |= TopAnchor;
+
+ if (!d->checkVValid()) {
+ d->usedAnchors &= ~TopAnchor;
+ return;
+ }
+
+ d->remDepend(d->top.item);
+ d->top = edge;
+ d->addDepend(d->top.item);
+ emit topChanged();
+ d->updateVerticalAnchors();
+}
+
+void QDeclarativeAnchors::resetTop()
+{
+ Q_D(QDeclarativeAnchors);
+ d->usedAnchors &= ~TopAnchor;
+ d->remDepend(d->top.item);
+ d->top = QDeclarativeAnchorLine();
+ emit topChanged();
+ d->updateVerticalAnchors();
+}
+
+QDeclarativeAnchorLine QDeclarativeAnchors::bottom() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->bottom;
+}
+
+void QDeclarativeAnchors::setBottom(const QDeclarativeAnchorLine &edge)
+{
+ Q_D(QDeclarativeAnchors);
+ if (!d->checkVAnchorValid(edge) || d->bottom == edge)
+ return;
+
+ d->usedAnchors |= BottomAnchor;
+
+ if (!d->checkVValid()) {
+ d->usedAnchors &= ~BottomAnchor;
+ return;
+ }
+
+ d->remDepend(d->bottom.item);
+ d->bottom = edge;
+ d->addDepend(d->bottom.item);
+ emit bottomChanged();
+ d->updateVerticalAnchors();
+}
+
+void QDeclarativeAnchors::resetBottom()
+{
+ Q_D(QDeclarativeAnchors);
+ d->usedAnchors &= ~BottomAnchor;
+ d->remDepend(d->bottom.item);
+ d->bottom = QDeclarativeAnchorLine();
+ emit bottomChanged();
+ d->updateVerticalAnchors();
+}
+
+QDeclarativeAnchorLine QDeclarativeAnchors::verticalCenter() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->vCenter;
+}
+
+void QDeclarativeAnchors::setVerticalCenter(const QDeclarativeAnchorLine &edge)
+{
+ Q_D(QDeclarativeAnchors);
+ if (!d->checkVAnchorValid(edge) || d->vCenter == edge)
+ return;
+
+ d->usedAnchors |= VCenterAnchor;
+
+ if (!d->checkVValid()) {
+ d->usedAnchors &= ~VCenterAnchor;
+ return;
+ }
+
+ d->remDepend(d->vCenter.item);
+ d->vCenter = edge;
+ d->addDepend(d->vCenter.item);
+ emit verticalCenterChanged();
+ d->updateVerticalAnchors();
+}
+
+void QDeclarativeAnchors::resetVerticalCenter()
+{
+ Q_D(QDeclarativeAnchors);
+ d->usedAnchors &= ~VCenterAnchor;
+ d->remDepend(d->vCenter.item);
+ d->vCenter = QDeclarativeAnchorLine();
+ emit verticalCenterChanged();
+ d->updateVerticalAnchors();
+}
+
+QDeclarativeAnchorLine QDeclarativeAnchors::baseline() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->baseline;
+}
+
+void QDeclarativeAnchors::setBaseline(const QDeclarativeAnchorLine &edge)
+{
+ Q_D(QDeclarativeAnchors);
+ if (!d->checkVAnchorValid(edge) || d->baseline == edge)
+ return;
+
+ d->usedAnchors |= BaselineAnchor;
+
+ if (!d->checkVValid()) {
+ d->usedAnchors &= ~BaselineAnchor;
+ return;
+ }
+
+ d->remDepend(d->baseline.item);
+ d->baseline = edge;
+ d->addDepend(d->baseline.item);
+ emit baselineChanged();
+ d->updateVerticalAnchors();
+}
+
+void QDeclarativeAnchors::resetBaseline()
+{
+ Q_D(QDeclarativeAnchors);
+ d->usedAnchors &= ~BaselineAnchor;
+ d->remDepend(d->baseline.item);
+ d->baseline = QDeclarativeAnchorLine();
+ emit baselineChanged();
+ d->updateVerticalAnchors();
+}
+
+QDeclarativeAnchorLine QDeclarativeAnchors::left() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->left;
+}
+
+void QDeclarativeAnchors::setLeft(const QDeclarativeAnchorLine &edge)
+{
+ Q_D(QDeclarativeAnchors);
+ if (!d->checkHAnchorValid(edge) || d->left == edge)
+ return;
+
+ d->usedAnchors |= LeftAnchor;
+
+ if (!d->checkHValid()) {
+ d->usedAnchors &= ~LeftAnchor;
+ return;
+ }
+
+ d->remDepend(d->left.item);
+ d->left = edge;
+ d->addDepend(d->left.item);
+ emit leftChanged();
+ d->updateHorizontalAnchors();
+}
+
+void QDeclarativeAnchors::resetLeft()
+{
+ Q_D(QDeclarativeAnchors);
+ d->usedAnchors &= ~LeftAnchor;
+ d->remDepend(d->left.item);
+ d->left = QDeclarativeAnchorLine();
+ emit leftChanged();
+ d->updateHorizontalAnchors();
+}
+
+QDeclarativeAnchorLine QDeclarativeAnchors::right() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->right;
+}
+
+void QDeclarativeAnchors::setRight(const QDeclarativeAnchorLine &edge)
+{
+ Q_D(QDeclarativeAnchors);
+ if (!d->checkHAnchorValid(edge) || d->right == edge)
+ return;
+
+ d->usedAnchors |= RightAnchor;
+
+ if (!d->checkHValid()) {
+ d->usedAnchors &= ~RightAnchor;
+ return;
+ }
+
+ d->remDepend(d->right.item);
+ d->right = edge;
+ d->addDepend(d->right.item);
+ emit rightChanged();
+ d->updateHorizontalAnchors();
+}
+
+void QDeclarativeAnchors::resetRight()
+{
+ Q_D(QDeclarativeAnchors);
+ d->usedAnchors &= ~RightAnchor;
+ d->remDepend(d->right.item);
+ d->right = QDeclarativeAnchorLine();
+ emit rightChanged();
+ d->updateHorizontalAnchors();
+}
+
+QDeclarativeAnchorLine QDeclarativeAnchors::horizontalCenter() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->hCenter;
+}
+
+void QDeclarativeAnchors::setHorizontalCenter(const QDeclarativeAnchorLine &edge)
+{
+ Q_D(QDeclarativeAnchors);
+ if (!d->checkHAnchorValid(edge) || d->hCenter == edge)
+ return;
+
+ d->usedAnchors |= HCenterAnchor;
+
+ if (!d->checkHValid()) {
+ d->usedAnchors &= ~HCenterAnchor;
+ return;
+ }
+
+ d->remDepend(d->hCenter.item);
+ d->hCenter = edge;
+ d->addDepend(d->hCenter.item);
+ emit horizontalCenterChanged();
+ d->updateHorizontalAnchors();
+}
+
+void QDeclarativeAnchors::resetHorizontalCenter()
+{
+ Q_D(QDeclarativeAnchors);
+ d->usedAnchors &= ~HCenterAnchor;
+ d->remDepend(d->hCenter.item);
+ d->hCenter = QDeclarativeAnchorLine();
+ emit horizontalCenterChanged();
+ d->updateHorizontalAnchors();
+}
+
+qreal QDeclarativeAnchors::leftMargin() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->leftMargin;
+}
+
+void QDeclarativeAnchors::setLeftMargin(qreal offset)
+{
+ Q_D(QDeclarativeAnchors);
+ if (d->leftMargin == offset)
+ return;
+ d->leftMargin = offset;
+ if(d->fill)
+ d->fillChanged();
+ else
+ d->updateHorizontalAnchors();
+ emit leftMarginChanged();
+}
+
+qreal QDeclarativeAnchors::rightMargin() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->rightMargin;
+}
+
+void QDeclarativeAnchors::setRightMargin(qreal offset)
+{
+ Q_D(QDeclarativeAnchors);
+ if (d->rightMargin == offset)
+ return;
+ d->rightMargin = offset;
+ if(d->fill)
+ d->fillChanged();
+ else
+ d->updateHorizontalAnchors();
+ emit rightMarginChanged();
+}
+
+qreal QDeclarativeAnchors::margins() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->margins;
+}
+
+void QDeclarativeAnchors::setMargins(qreal offset)
+{
+ Q_D(QDeclarativeAnchors);
+ if (d->margins == offset)
+ return;
+ //###Is it significantly faster to set them directly so we can call fillChanged only once?
+ if(!d->rightMargin || d->rightMargin == d->margins)
+ setRightMargin(offset);
+ if(!d->leftMargin || d->leftMargin == d->margins)
+ setLeftMargin(offset);
+ if(!d->topMargin || d->topMargin == d->margins)
+ setTopMargin(offset);
+ if(!d->bottomMargin || d->bottomMargin == d->margins)
+ setBottomMargin(offset);
+ d->margins = offset;
+ emit marginsChanged();
+
+}
+
+qreal QDeclarativeAnchors::horizontalCenterOffset() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->hCenterOffset;
+}
+
+void QDeclarativeAnchors::setHorizontalCenterOffset(qreal offset)
+{
+ Q_D(QDeclarativeAnchors);
+ if (d->hCenterOffset == offset)
+ return;
+ d->hCenterOffset = offset;
+ if(d->centerIn)
+ d->centerInChanged();
+ else
+ d->updateHorizontalAnchors();
+ emit horizontalCenterOffsetChanged();
+}
+
+qreal QDeclarativeAnchors::topMargin() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->topMargin;
+}
+
+void QDeclarativeAnchors::setTopMargin(qreal offset)
+{
+ Q_D(QDeclarativeAnchors);
+ if (d->topMargin == offset)
+ return;
+ d->topMargin = offset;
+ if(d->fill)
+ d->fillChanged();
+ else
+ d->updateVerticalAnchors();
+ emit topMarginChanged();
+}
+
+qreal QDeclarativeAnchors::bottomMargin() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->bottomMargin;
+}
+
+void QDeclarativeAnchors::setBottomMargin(qreal offset)
+{
+ Q_D(QDeclarativeAnchors);
+ if (d->bottomMargin == offset)
+ return;
+ d->bottomMargin = offset;
+ if(d->fill)
+ d->fillChanged();
+ else
+ d->updateVerticalAnchors();
+ emit bottomMarginChanged();
+}
+
+qreal QDeclarativeAnchors::verticalCenterOffset() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->vCenterOffset;
+}
+
+void QDeclarativeAnchors::setVerticalCenterOffset(qreal offset)
+{
+ Q_D(QDeclarativeAnchors);
+ if (d->vCenterOffset == offset)
+ return;
+ d->vCenterOffset = offset;
+ if(d->centerIn)
+ d->centerInChanged();
+ else
+ d->updateVerticalAnchors();
+ emit verticalCenterOffsetChanged();
+}
+
+qreal QDeclarativeAnchors::baselineOffset() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->baselineOffset;
+}
+
+void QDeclarativeAnchors::setBaselineOffset(qreal offset)
+{
+ Q_D(QDeclarativeAnchors);
+ if (d->baselineOffset == offset)
+ return;
+ d->baselineOffset = offset;
+ d->updateVerticalAnchors();
+ emit baselineOffsetChanged();
+}
+
+QDeclarativeAnchors::Anchors QDeclarativeAnchors::usedAnchors() const
+{
+ Q_D(const QDeclarativeAnchors);
+ return d->usedAnchors;
+}
+
+bool QDeclarativeAnchorsPrivate::checkHValid() const
+{
+ if (usedAnchors & QDeclarativeAnchors::LeftAnchor &&
+ usedAnchors & QDeclarativeAnchors::RightAnchor &&
+ usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
+ qmlInfo(item) << QDeclarativeAnchors::tr("Cannot specify left, right, and hcenter anchors.");
+ return false;
+ }
+
+ return true;
+}
+
+bool QDeclarativeAnchorsPrivate::checkHAnchorValid(QDeclarativeAnchorLine anchor) const
+{
+ if (!anchor.item) {
+ qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor to a null item.");
+ return false;
+ } else if (anchor.anchorLine & QDeclarativeAnchorLine::Vertical_Mask) {
+ qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor a horizontal edge to a vertical edge.");
+ return false;
+ } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
+ qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
+ return false;
+ } else if (anchor.item == item) {
+ qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor item to self.");
+ return false;
+ }
+
+ return true;
+}
+
+bool QDeclarativeAnchorsPrivate::checkVValid() const
+{
+ if (usedAnchors & QDeclarativeAnchors::TopAnchor &&
+ usedAnchors & QDeclarativeAnchors::BottomAnchor &&
+ usedAnchors & QDeclarativeAnchors::VCenterAnchor) {
+ qmlInfo(item) << QDeclarativeAnchors::tr("Cannot specify top, bottom, and vcenter anchors.");
+ return false;
+ } else if (usedAnchors & QDeclarativeAnchors::BaselineAnchor &&
+ (usedAnchors & QDeclarativeAnchors::TopAnchor ||
+ usedAnchors & QDeclarativeAnchors::BottomAnchor ||
+ usedAnchors & QDeclarativeAnchors::VCenterAnchor)) {
+ qmlInfo(item) << QDeclarativeAnchors::tr("Baseline anchor cannot be used in conjunction with top, bottom, or vcenter anchors.");
+ return false;
+ }
+
+ return true;
+}
+
+bool QDeclarativeAnchorsPrivate::checkVAnchorValid(QDeclarativeAnchorLine anchor) const
+{
+ if (!anchor.item) {
+ qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor to a null item.");
+ return false;
+ } else if (anchor.anchorLine & QDeclarativeAnchorLine::Horizontal_Mask) {
+ qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor a vertical edge to a horizontal edge.");
+ return false;
+ } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
+ qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
+ return false;
+ } else if (anchor.item == item){
+ qmlInfo(item) << QDeclarativeAnchors::tr("Cannot anchor item to self.");
+ return false;
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#include <moc_qdeclarativeanchors_p.cpp>
+
diff --git a/src/declarative/graphicsitems/qdeclarativeanchors_p.h b/src/declarative/graphicsitems/qdeclarativeanchors_p.h
new file mode 100644
index 00000000..6297febd
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeanchors_p.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEANCHORS_H
+#define QDECLARATIVEANCHORS_H
+
+#include "qdeclarativeitem.h"
+
+#include <qdeclarative.h>
+
+#include <QtCore/QObject>
+
+#include <private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeAnchorsPrivate;
+class QDeclarativeAnchorLine;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeAnchors : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QDeclarativeAnchorLine left READ left WRITE setLeft RESET resetLeft NOTIFY leftChanged)
+ Q_PROPERTY(QDeclarativeAnchorLine right READ right WRITE setRight RESET resetRight NOTIFY rightChanged)
+ Q_PROPERTY(QDeclarativeAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter NOTIFY horizontalCenterChanged)
+ Q_PROPERTY(QDeclarativeAnchorLine top READ top WRITE setTop RESET resetTop NOTIFY topChanged)
+ Q_PROPERTY(QDeclarativeAnchorLine bottom READ bottom WRITE setBottom RESET resetBottom NOTIFY bottomChanged)
+ Q_PROPERTY(QDeclarativeAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter NOTIFY verticalCenterChanged)
+ Q_PROPERTY(QDeclarativeAnchorLine 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(QGraphicsObject *fill READ fill WRITE setFill RESET resetFill NOTIFY fillChanged)
+ Q_PROPERTY(QGraphicsObject *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn NOTIFY centerInChanged)
+
+public:
+ QDeclarativeAnchors(QObject *parent=0);
+ QDeclarativeAnchors(QGraphicsObject *item, QObject *parent=0);
+ virtual ~QDeclarativeAnchors();
+
+ 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)
+
+ QDeclarativeAnchorLine left() const;
+ void setLeft(const QDeclarativeAnchorLine &edge);
+ void resetLeft();
+
+ QDeclarativeAnchorLine right() const;
+ void setRight(const QDeclarativeAnchorLine &edge);
+ void resetRight();
+
+ QDeclarativeAnchorLine horizontalCenter() const;
+ void setHorizontalCenter(const QDeclarativeAnchorLine &edge);
+ void resetHorizontalCenter();
+
+ QDeclarativeAnchorLine top() const;
+ void setTop(const QDeclarativeAnchorLine &edge);
+ void resetTop();
+
+ QDeclarativeAnchorLine bottom() const;
+ void setBottom(const QDeclarativeAnchorLine &edge);
+ void resetBottom();
+
+ QDeclarativeAnchorLine verticalCenter() const;
+ void setVerticalCenter(const QDeclarativeAnchorLine &edge);
+ void resetVerticalCenter();
+
+ QDeclarativeAnchorLine baseline() const;
+ void setBaseline(const QDeclarativeAnchorLine &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);
+
+ QGraphicsObject *fill() const;
+ void setFill(QGraphicsObject *);
+ void resetFill();
+
+ QGraphicsObject *centerIn() const;
+ void setCenterIn(QGraphicsObject *);
+ void resetCenterIn();
+
+ Anchors usedAnchors() const;
+
+ void classBegin();
+ void componentComplete();
+
+ bool mirrored();
+
+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();
+
+private:
+ friend class QDeclarativeItem;
+ friend class QDeclarativeItemPrivate;
+ friend class QDeclarativeGraphicsWidget;
+ Q_DISABLE_COPY(QDeclarativeAnchors)
+ Q_DECLARE_PRIVATE(QDeclarativeAnchors)
+ Q_PRIVATE_SLOT(d_func(), void _q_widgetGeometryChanged())
+ Q_PRIVATE_SLOT(d_func(), void _q_widgetDestroyed(QObject *obj))
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeAnchors::Anchors)
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeAnchors)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h b/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h
new file mode 100644
index 00000000..f76443c0
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEANCHORS_P_H
+#define QDECLARATIVEANCHORS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeanchors_p.h"
+#include "private/qdeclarativeitemchangelistener_p.h"
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeAnchorLine
+{
+public:
+ QDeclarativeAnchorLine() : item(0), anchorLine(Invalid) {}
+
+ enum AnchorLine {
+ Invalid = 0x0,
+ Left = 0x01,
+ Right = 0x02,
+ Top = 0x04,
+ Bottom = 0x08,
+ HCenter = 0x10,
+ VCenter = 0x20,
+ Baseline = 0x40,
+ Horizontal_Mask = Left | Right | HCenter,
+ Vertical_Mask = Top | Bottom | VCenter | Baseline
+ };
+
+ QGraphicsObject *item;
+ AnchorLine anchorLine;
+};
+
+inline bool operator==(const QDeclarativeAnchorLine& a, const QDeclarativeAnchorLine& b)
+{
+ return a.item == b.item && a.anchorLine == b.anchorLine;
+}
+
+class QDeclarativeAnchorsPrivate : public QObjectPrivate, public QDeclarativeItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QDeclarativeAnchors)
+public:
+ QDeclarativeAnchorsPrivate(QGraphicsObject *i)
+ : componentComplete(true), updatingMe(false), updatingHorizontalAnchor(0),
+ updatingVerticalAnchor(0), updatingFill(0), updatingCenterIn(0), item(i), usedAnchors(0), fill(0),
+ centerIn(0), leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0),
+ margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0)
+ {
+ }
+
+ void clearItem(QGraphicsObject *);
+
+ void addDepend(QGraphicsObject *);
+ void remDepend(QGraphicsObject *);
+ bool isItemComplete() const;
+
+ bool componentComplete:1;
+ bool updatingMe:1;
+ uint updatingHorizontalAnchor:2;
+ uint updatingVerticalAnchor:2;
+ uint updatingFill:2;
+ uint updatingCenterIn:2;
+
+ void setItemHeight(qreal);
+ void setItemWidth(qreal);
+ void setItemX(qreal);
+ void setItemY(qreal);
+ void setItemPos(const QPointF &);
+ void setItemSize(const QSizeF &);
+
+ void updateOnComplete();
+ void updateMe();
+
+ // QDeclarativeItemGeometryListener interface
+ void itemGeometryChanged(QDeclarativeItem *, const QRectF &, const QRectF &);
+ void _q_widgetDestroyed(QObject *);
+ void _q_widgetGeometryChanged();
+ QDeclarativeAnchorsPrivate *anchorPrivate() { return this; }
+
+ bool checkHValid() const;
+ bool checkVValid() const;
+ bool checkHAnchorValid(QDeclarativeAnchorLine anchor) const;
+ bool checkVAnchorValid(QDeclarativeAnchorLine anchor) const;
+ bool calcStretch(const QDeclarativeAnchorLine &edge1, const QDeclarativeAnchorLine &edge2, qreal offset1, qreal offset2, QDeclarativeAnchorLine::AnchorLine line, qreal &stretch);
+
+ bool isMirrored() const;
+ void updateHorizontalAnchors();
+ void updateVerticalAnchors();
+ void fillChanged();
+ void centerInChanged();
+
+ QGraphicsObject *item;
+ QDeclarativeAnchors::Anchors usedAnchors;
+
+ QGraphicsObject *fill;
+ QGraphicsObject *centerIn;
+
+ QDeclarativeAnchorLine left;
+ QDeclarativeAnchorLine right;
+ QDeclarativeAnchorLine top;
+ QDeclarativeAnchorLine bottom;
+ QDeclarativeAnchorLine vCenter;
+ QDeclarativeAnchorLine hCenter;
+ QDeclarativeAnchorLine baseline;
+
+ qreal leftMargin;
+ qreal rightMargin;
+ qreal topMargin;
+ qreal bottomMargin;
+ qreal margins;
+ qreal vCenterOffset;
+ qreal hCenterOffset;
+ qreal baselineOffset;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QDeclarativeAnchorLine)
+
+#endif
diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp
new file mode 100644
index 00000000..49a8dfd2
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp
@@ -0,0 +1,404 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativeanimatedimage_p.h"
+#include "private/qdeclarativeanimatedimage_p_p.h"
+
+#ifndef QT_NO_MOVIE
+
+#include <qdeclarativeinfo.h>
+#include <private/qdeclarativeengine_p.h>
+
+#include <QMovie>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass AnimatedImage QDeclarativeAnimatedImage
+ \inherits Image
+ \since 4.7
+ \ingroup basic-visual-elements
+
+ The AnimatedImage element extends the features of the \l Image element, providing
+ a way to play animations stored as images containing a series of frames,
+ such as those stored in GIF files.
+
+ Information about the current frame and totla length of the animation can be
+ obtained using the \l currentFrame and \l frameCount properties. You can
+ start, pause and stop the animation by changing the values of the \l playing
+ and \l paused properties.
+
+ The full list of supported formats can be determined with QMovie::supportedFormats().
+
+ \section1 Example Usage
+
+ \beginfloatleft
+ \image animatedimageitem.gif
+ \endfloat
+
+ The following QML shows how to display an animated image and obtain information
+ about its state, such as the current frame and total number of frames.
+ The result is an animated image with a simple progress indicator underneath it.
+
+ \clearfloat
+ \snippet doc/src/snippets/declarative/animatedimage.qml document
+
+ \sa BorderImage, Image
+*/
+
+/*!
+ \qmlproperty url AnimatedImage::source
+
+ This property holds the URL that refers to the source image.
+
+ AnimatedImage can handle any image format supported by Qt, loaded from any
+ URL scheme supported by Qt.
+
+ \sa QDeclarativeImageProvider
+*/
+
+/*!
+ \qmlproperty bool AnimatedImage::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 asynchonously.
+*/
+
+/*!
+ \qmlproperty bool AnimatedImage::cache
+ \since QtQuick 1.1
+
+ 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 AnimatedImage::mirror
+ \since QtQuick 1.1
+
+ This property holds whether the image should be horizontally inverted
+ (effectively displaying a mirrored image).
+
+ The default value is false.
+*/
+
+QDeclarativeAnimatedImage::QDeclarativeAnimatedImage(QDeclarativeItem *parent)
+ : QDeclarativeImage(*(new QDeclarativeAnimatedImagePrivate), parent)
+{
+}
+
+QDeclarativeAnimatedImage::~QDeclarativeAnimatedImage()
+{
+ Q_D(QDeclarativeAnimatedImage);
+ delete d->_movie;
+}
+
+/*!
+ \qmlproperty bool AnimatedImage::paused
+ This property holds whether the animated image is paused.
+
+ By default, this property is false. Set it to true when you want to pause
+ the animation.
+*/
+bool QDeclarativeAnimatedImage::isPaused() const
+{
+ Q_D(const QDeclarativeAnimatedImage);
+ if(!d->_movie)
+ return false;
+ return d->_movie->state()==QMovie::Paused;
+}
+
+void QDeclarativeAnimatedImage::setPaused(bool pause)
+{
+ Q_D(QDeclarativeAnimatedImage);
+ if(pause == d->paused)
+ return;
+ d->paused = pause;
+ if(!d->_movie)
+ return;
+ d->_movie->setPaused(pause);
+}
+/*!
+ \qmlproperty bool AnimatedImage::playing
+ This property holds whether the animated image is playing.
+
+ By default, this property is true, meaning that the animation
+ will start playing immediately.
+*/
+bool QDeclarativeAnimatedImage::isPlaying() const
+{
+ Q_D(const QDeclarativeAnimatedImage);
+ if (!d->_movie)
+ return false;
+ return d->_movie->state()!=QMovie::NotRunning;
+}
+
+void QDeclarativeAnimatedImage::setPlaying(bool play)
+{
+ Q_D(QDeclarativeAnimatedImage);
+ if(play == d->playing)
+ return;
+ d->playing = play;
+ if (!d->_movie)
+ return;
+ if (play)
+ d->_movie->start();
+ else
+ d->_movie->stop();
+}
+
+/*!
+ \qmlproperty int AnimatedImage::currentFrame
+ \qmlproperty int AnimatedImage::frameCount
+
+ currentFrame is the frame that is currently visible. By monitoring this property
+ for changes, you can animate other items at the same time as the image.
+
+ frameCount is the number of frames in the animation. For some animation formats,
+ frameCount is unknown and has a value of zero.
+*/
+int QDeclarativeAnimatedImage::currentFrame() const
+{
+ Q_D(const QDeclarativeAnimatedImage);
+ if (!d->_movie)
+ return d->preset_currentframe;
+ return d->_movie->currentFrameNumber();
+}
+
+void QDeclarativeAnimatedImage::setCurrentFrame(int frame)
+{
+ Q_D(QDeclarativeAnimatedImage);
+ if (!d->_movie) {
+ d->preset_currentframe = frame;
+ return;
+ }
+ d->_movie->jumpToFrame(frame);
+}
+
+int QDeclarativeAnimatedImage::frameCount() const
+{
+ Q_D(const QDeclarativeAnimatedImage);
+ if (!d->_movie)
+ return 0;
+ return d->_movie->frameCount();
+}
+
+void QDeclarativeAnimatedImage::setSource(const QUrl &url)
+{
+ Q_D(QDeclarativeAnimatedImage);
+ if (url == d->url)
+ return;
+
+ delete d->_movie;
+ d->_movie = 0;
+
+ if (d->reply) {
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+
+ d->url = url;
+ emit sourceChanged(d->url);
+
+ if (isComponentComplete())
+ load();
+}
+
+void QDeclarativeAnimatedImage::load()
+{
+ Q_D(QDeclarativeAnimatedImage);
+
+ QDeclarativeImageBase::Status oldStatus = d->status;
+ qreal oldProgress = d->progress;
+
+ if (d->url.isEmpty()) {
+ delete d->_movie;
+ d->setPixmap(QPixmap());
+ d->progress = 0;
+ d->status = Null;
+ if (d->status != oldStatus)
+ emit statusChanged(d->status);
+ if (d->progress != oldProgress)
+ emit progressChanged(d->progress);
+ } else {
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url);
+ if (!lf.isEmpty()) {
+ //### should be unified with movieRequestFinished
+ d->_movie = new QMovie(lf);
+ if (!d->_movie->isValid()){
+ qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString();
+ delete d->_movie;
+ d->_movie = 0;
+ d->status = Error;
+ if (d->status != oldStatus)
+ emit statusChanged(d->status);
+ return;
+ }
+ connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
+ this, SLOT(playingStatusChanged()));
+ connect(d->_movie, SIGNAL(frameChanged(int)),
+ this, SLOT(movieUpdate()));
+ d->_movie->setCacheMode(QMovie::CacheAll);
+ if(d->playing)
+ d->_movie->start();
+ else
+ d->_movie->jumpToFrame(0);
+ if(d->paused)
+ d->_movie->setPaused(true);
+ d->setPixmap(d->_movie->currentPixmap());
+ d->status = Ready;
+ d->progress = 1.0;
+ if (d->status != oldStatus)
+ emit statusChanged(d->status);
+ if (d->progress != oldProgress)
+ emit progressChanged(d->progress);
+ return;
+ }
+#endif
+ d->status = Loading;
+ d->progress = 0;
+ emit statusChanged(d->status);
+ emit progressChanged(d->progress);
+ QNetworkRequest req(d->url);
+ req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
+ d->reply = qmlEngine(this)->networkAccessManager()->get(req);
+ QObject::connect(d->reply, SIGNAL(finished()),
+ this, SLOT(movieRequestFinished()));
+ QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ }
+}
+
+#define ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION 16
+
+void QDeclarativeAnimatedImage::movieRequestFinished()
+{
+ Q_D(QDeclarativeAnimatedImage);
+
+ d->redirectCount++;
+ if (d->redirectCount < ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION) {
+ QVariant redirect = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirect.isValid()) {
+ QUrl url = d->reply->url().resolved(redirect.toUrl());
+ d->reply->deleteLater();
+ d->reply = 0;
+ setSource(url);
+ return;
+ }
+ }
+ d->redirectCount=0;
+
+ d->_movie = new QMovie(d->reply);
+ if (!d->_movie->isValid()){
+#ifndef QT_NO_DEBUG_STREAM
+ qmlInfo(this) << "Error Reading Animated Image File " << d->url;
+#endif
+ delete d->_movie;
+ d->_movie = 0;
+ d->status = Error;
+ emit statusChanged(d->status);
+ return;
+ }
+ connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
+ this, SLOT(playingStatusChanged()));
+ connect(d->_movie, SIGNAL(frameChanged(int)),
+ this, SLOT(movieUpdate()));
+ d->_movie->setCacheMode(QMovie::CacheAll);
+ if(d->playing)
+ d->_movie->start();
+ if (d->paused || !d->playing) {
+ d->_movie->jumpToFrame(d->preset_currentframe);
+ d->preset_currentframe = 0;
+ }
+ if(d->paused)
+ d->_movie->setPaused(true);
+ d->setPixmap(d->_movie->currentPixmap());
+ d->status = Ready;
+ emit statusChanged(d->status);
+}
+
+void QDeclarativeAnimatedImage::movieUpdate()
+{
+ Q_D(QDeclarativeAnimatedImage);
+ d->setPixmap(d->_movie->currentPixmap());
+ emit frameChanged();
+}
+
+void QDeclarativeAnimatedImage::playingStatusChanged()
+{
+ Q_D(QDeclarativeAnimatedImage);
+ if((d->_movie->state() != QMovie::NotRunning) != d->playing){
+ d->playing = (d->_movie->state() != QMovie::NotRunning);
+ emit playingChanged();
+ }
+ if((d->_movie->state() == QMovie::Paused) != d->paused){
+ d->playing = (d->_movie->state() == QMovie::Paused);
+ emit pausedChanged();
+ }
+}
+
+void QDeclarativeAnimatedImage::componentComplete()
+{
+ Q_D(QDeclarativeAnimatedImage);
+ QDeclarativeItem::componentComplete(); // NOT QDeclarativeImage
+ if (d->url.isValid())
+ load();
+ if (!d->reply) {
+ setCurrentFrame(d->preset_currentframe);
+ d->preset_currentframe = 0;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_MOVIE
diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h b/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h
new file mode 100644
index 00000000..a72ce782
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEANIMATEDIMAGE_H
+#define QDECLARATIVEANIMATEDIMAGE_H
+
+#include "private/qdeclarativeimage_p.h"
+
+#ifndef QT_NO_MOVIE
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QMovie;
+class QDeclarativeAnimatedImagePrivate;
+
+class Q_AUTOTEST_EXPORT QDeclarativeAnimatedImage : public QDeclarativeImage
+{
+ 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:
+ QDeclarativeAnimatedImage(QDeclarativeItem *parent=0);
+ ~QDeclarativeAnimatedImage();
+
+ 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 QDeclarativeImage'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(QDeclarativeAnimatedImage)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeAnimatedImage)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeAnimatedImage)
+
+QT_END_HEADER
+
+#endif // QT_NO_MOVIE
+
+#endif
diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage_p_p.h b/src/declarative/graphicsitems/qdeclarativeanimatedimage_p_p.h
new file mode 100644
index 00000000..36891d1b
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage_p_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEANIMATEDIMAGE_P_H
+#define QDECLARATIVEANIMATEDIMAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeimage_p_p.h"
+
+#ifndef QT_NO_MOVIE
+
+QT_BEGIN_NAMESPACE
+
+class QMovie;
+class QNetworkReply;
+
+class QDeclarativeAnimatedImagePrivate : public QDeclarativeImagePrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarativeAnimatedImage)
+
+public:
+ QDeclarativeAnimatedImagePrivate()
+ : playing(true), paused(false), preset_currentframe(0), _movie(0), reply(0), redirectCount(0)
+ {
+ }
+
+ bool playing;
+ bool paused;
+ int preset_currentframe;
+ QMovie *_movie;
+ QNetworkReply *reply;
+ int redirectCount;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_MOVIE
+
+#endif // QDECLARATIVEANIMATEDIMAGE_P_H
diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp
new file mode 100644
index 00000000..5babbb2b
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp
@@ -0,0 +1,623 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativeborderimage_p.h"
+#include "private/qdeclarativeborderimage_p_p.h"
+
+#include <qdeclarativeinfo.h>
+#include <private/qdeclarativeengine_p.h>
+
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QFile>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass BorderImage QDeclarativeBorderImage
+ \brief The BorderImage element provides an image that can be used as a border.
+ \inherits Item
+ \since 4.7
+ \ingroup qml-basic-visual-elements
+
+ The BorderImage element is used to create borders out of images by scaling or tiling
+ parts of each image.
+
+ A BorderImage element breaks a source image, specified using the \l url property,
+ into 9 regions, as shown below:
+
+ \image declarative-scalegrid.png
+
+ When the image is scaled, regions of the source image are scaled or tiled to
+ create the displayed border image in the following way:
+
+ \list
+ \i The corners (regions 1, 3, 7, and 9) are not scaled at all.
+ \i Regions 2 and 8 are scaled according to
+ \l{BorderImage::horizontalTileMode}{horizontalTileMode}.
+ \i Regions 4 and 6 are scaled according to
+ \l{BorderImage::verticalTileMode}{verticalTileMode}.
+ \i The middle (region 5) is scaled according to both
+ \l{BorderImage::horizontalTileMode}{horizontalTileMode} and
+ \l{BorderImage::verticalTileMode}{verticalTileMode}.
+ \endlist
+
+ The regions of the image are defined using the \l border property group, which
+ describes the distance from each edge of the source image to use as a border.
+
+ \section1 Example Usage
+
+ The following examples show the effects of the different modes on an image.
+ Guide lines are overlaid onto the image to show the different regions of the
+ image as described above.
+
+ \beginfloatleft
+ \image qml-borderimage-normal-image.png
+ \endfloat
+
+ An unscaled image is displayed using an Image element. The \l border property is
+ used to determine the parts of the image that will lie inside the unscaled corner
+ areas and the parts that will be stretched horizontally and vertically.
+
+ \snippet doc/src/snippets/declarative/borderimage/normal-image.qml normal image
+
+ \clearfloat
+ \beginfloatleft
+ \image qml-borderimage-scaled.png
+ \endfloat
+
+ A BorderImage element is used to display the image, and it is given a size that is
+ larger than the original image. Since the \l horizontalTileMode property is set to
+ \l{BorderImage::horizontalTileMode}{BorderImage.Stretch}, the parts of image in
+ regions 2 and 8 are stretched horizontally. Since the \l verticalTileMode property
+ is set to \l{BorderImage::verticalTileMode}{BorderImage.Stretch}, the parts of image
+ in regions 4 and 6 are stretched vertically.
+
+ \snippet doc/src/snippets/declarative/borderimage/borderimage-scaled.qml scaled border image
+
+ \clearfloat
+ \beginfloatleft
+ \image qml-borderimage-tiled.png
+ \endfloat
+
+ Again, a large BorderImage element is used to display the image. With the
+ \l horizontalTileMode property set to \l{BorderImage::horizontalTileMode}{BorderImage.Repeat},
+ the parts of image in regions 2 and 8 are tiled so that they fill the space at the
+ top and bottom of the element. Similarly, the \l verticalTileMode property is set to
+ \l{BorderImage::verticalTileMode}{BorderImage.Repeat}, the parts of image in regions
+ 4 and 6 are tiled so that they fill the space at the left and right of the element.
+
+ \snippet doc/src/snippets/declarative/borderimage/borderimage-tiled.qml tiled border image
+
+ \clearfloat
+ In some situations, the width of regions 2 and 8 may not be an exact multiple of the width
+ of the corresponding regions in the source image. Similarly, the height of regions 4 and 6
+ may not be an exact multiple of the height of the corresponding regions. It can be useful
+ to use \l{BorderImage::horizontalTileMode}{BorderImage.Round} instead of
+ \l{BorderImage::horizontalTileMode}{BorderImage.Repeat} in cases like these.
+
+ The \l{declarative/imageelements/borderimage}{BorderImage example} shows how a BorderImage
+ can be used to simulate a shadow effect on a rectangular item.
+
+ \section1 Quality and Performance
+
+ By default, any scaled regions of the image are rendered without smoothing to improve
+ rendering speed. Setting the \l smooth property improves rendering quality of scaled
+ regions, but may slow down rendering.
+
+ The source image may not be loaded instantaneously, depending on its original location.
+ Loading progress can be monitored with the \l progress property.
+
+ \sa Image, AnimatedImage
+ */
+
+/*!
+ \qmlproperty bool BorderImage::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 asynchonously.
+*/
+QDeclarativeBorderImage::QDeclarativeBorderImage(QDeclarativeItem *parent)
+ : QDeclarativeImageBase(*(new QDeclarativeBorderImagePrivate), parent)
+{
+}
+
+QDeclarativeBorderImage::~QDeclarativeBorderImage()
+{
+ Q_D(QDeclarativeBorderImage);
+ if (d->sciReply)
+ d->sciReply->deleteLater();
+}
+/*!
+ \qmlproperty enumeration BorderImage::status
+
+ This property describes the status of image loading. It can be one of:
+
+ \list
+ \o BorderImage.Null - no image has been set
+ \o BorderImage.Ready - the image has been loaded
+ \o BorderImage.Loading - the image is currently being loaded
+ \o BorderImage.Error - an error occurred while loading the image
+ \endlist
+
+ \sa progress
+*/
+
+/*!
+ \qmlproperty real BorderImage::progress
+
+ This property holds the progress of image loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+
+/*!
+ \qmlproperty bool BorderImage::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.
+
+ By default, this property is set to false.
+
+ \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 enable it at the conclusion.
+*/
+
+/*!
+ \qmlproperty bool BorderImage::cache
+ \since QtQuick 1.1
+
+ 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 BorderImage::mirror
+ \since QtQuick 1.1
+
+ This property holds whether the image should be horizontally inverted
+ (effectively displaying a mirrored image).
+
+ The default value is false.
+*/
+
+/*!
+ \qmlproperty url BorderImage::source
+
+ This property holds the URL that refers to the source image.
+
+ BorderImage can handle any image format supported by Qt, loaded from any
+ URL scheme supported by Qt.
+
+ This property can also be used to refer to .sci files, which are
+ written in a QML-specific, text-based format that specifies the
+ borders, the image file and the tile rules for a given border image.
+
+ The following .sci file sets the borders to 10 on each side for the
+ image \c picture.png:
+
+ \code
+ border.left: 10
+ border.top: 10
+ border.bottom: 10
+ border.right: 10
+ source: "picture.png"
+ \endcode
+
+ The URL may be absolute, or relative to the URL of the component.
+
+ \sa QDeclarativeImageProvider
+*/
+
+/*!
+ \qmlproperty QSize BorderImage::sourceSize
+
+ This property holds the actual width and height of the loaded image.
+
+ In BorderImage, this property is read-only.
+
+ \sa Image::sourceSize
+*/
+void QDeclarativeBorderImage::setSource(const QUrl &url)
+{
+ Q_D(QDeclarativeBorderImage);
+ //equality is fairly expensive, so we bypass for simple, common case
+ if ((d->url.isEmpty() == url.isEmpty()) && url == d->url)
+ return;
+
+ if (d->sciReply) {
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ }
+
+ d->url = url;
+ d->sciurl = QUrl();
+ emit sourceChanged(d->url);
+
+ if (isComponentComplete())
+ load();
+}
+
+void QDeclarativeBorderImage::setSourceSize(const QSize& size)
+{
+ Q_UNUSED(size);
+ qmlInfo(this) << "Setting sourceSize for borderImage not supported";
+}
+
+void QDeclarativeBorderImage::load()
+{
+ Q_D(QDeclarativeBorderImage);
+ if (d->progress != 0.0) {
+ d->progress = 0.0;
+ emit progressChanged(d->progress);
+ }
+
+ if (d->url.isEmpty()) {
+ d->pix.clear(this);
+ d->status = Null;
+ setImplicitWidth(0);
+ setImplicitHeight(0);
+ emit statusChanged(d->status);
+ update();
+ } else {
+ d->status = Loading;
+ if (d->url.path().endsWith(QLatin1String("sci"))) {
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url);
+ if (!lf.isEmpty()) {
+ QFile file(lf);
+ file.open(QIODevice::ReadOnly);
+ setGridScaledImage(QDeclarativeGridScaledImage(&file));
+ } else
+#endif
+ {
+ QNetworkRequest req(d->url);
+ d->sciReply = qmlEngine(this)->networkAccessManager()->get(req);
+
+ static int sciReplyFinished = -1;
+ static int thisSciRequestFinished = -1;
+ if (sciReplyFinished == -1) {
+ sciReplyFinished =
+ QNetworkReply::staticMetaObject.indexOfSignal("finished()");
+ thisSciRequestFinished =
+ QDeclarativeBorderImage::staticMetaObject.indexOfSlot("sciRequestFinished()");
+ }
+
+ QMetaObject::connect(d->sciReply, sciReplyFinished, this,
+ thisSciRequestFinished, Qt::DirectConnection);
+ }
+ } else {
+
+ QDeclarativePixmap::Options options;
+ if (d->async)
+ options |= QDeclarativePixmap::Asynchronous;
+ if (d->cache)
+ options |= QDeclarativePixmap::Cache;
+ d->pix.clear(this);
+ d->pix.load(qmlEngine(this), d->url, options);
+
+ if (d->pix.isLoading()) {
+ d->pix.connectFinished(this, SLOT(requestFinished()));
+ d->pix.connectDownloadProgress(this, SLOT(requestProgress(qint64,qint64)));
+ } else {
+ QSize impsize = d->pix.implicitSize();
+ setImplicitWidth(impsize.width());
+ setImplicitHeight(impsize.height());
+
+ if (d->pix.isReady()) {
+ d->status = Ready;
+ } else {
+ d->status = Error;
+ qmlInfo(this) << d->pix.error();
+ }
+
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit progressChanged(d->progress);
+ requestFinished();
+ update();
+ }
+ }
+ }
+
+ emit statusChanged(d->status);
+}
+
+/*!
+ \qmlproperty int BorderImage::border.left
+ \qmlproperty int BorderImage::border.right
+ \qmlproperty int BorderImage::border.top
+ \qmlproperty int BorderImage::border.bottom
+
+ The 4 border lines (2 horizontal and 2 vertical) break the image into 9 sections,
+ as shown below:
+
+ \image declarative-scalegrid.png
+
+ Each border line (left, right, top, and bottom) specifies an offset in pixels
+ from the respective edge of the source image. By default, each border line has
+ a value of 0.
+
+ For example, the following definition sets the bottom line 10 pixels up from
+ the bottom of the image:
+
+ \qml
+ BorderImage {
+ border.bottom: 10
+ // ...
+ }
+ \endqml
+
+ The border lines can also be specified using a
+ \l {BorderImage::source}{.sci file}.
+*/
+
+QDeclarativeScaleGrid *QDeclarativeBorderImage::border()
+{
+ Q_D(QDeclarativeBorderImage);
+ return d->getScaleGrid();
+}
+
+/*!
+ \qmlproperty enumeration BorderImage::horizontalTileMode
+ \qmlproperty enumeration BorderImage::verticalTileMode
+
+ This property describes how to repeat or stretch the middle parts of the border image.
+
+ \list
+ \o BorderImage.Stretch - Scales the image to fit to the available area.
+ \o BorderImage.Repeat - Tile the image until there is no more space. May crop the last image.
+ \o BorderImage.Round - Like Repeat, but scales the images down to ensure that the last image is not cropped.
+ \endlist
+
+ The default tile mode for each property is BorderImage.Stretch.
+*/
+QDeclarativeBorderImage::TileMode QDeclarativeBorderImage::horizontalTileMode() const
+{
+ Q_D(const QDeclarativeBorderImage);
+ return d->horizontalTileMode;
+}
+
+void QDeclarativeBorderImage::setHorizontalTileMode(TileMode t)
+{
+ Q_D(QDeclarativeBorderImage);
+ if (t != d->horizontalTileMode) {
+ d->horizontalTileMode = t;
+ emit horizontalTileModeChanged();
+ update();
+ }
+}
+
+QDeclarativeBorderImage::TileMode QDeclarativeBorderImage::verticalTileMode() const
+{
+ Q_D(const QDeclarativeBorderImage);
+ return d->verticalTileMode;
+}
+
+void QDeclarativeBorderImage::setVerticalTileMode(TileMode t)
+{
+ Q_D(QDeclarativeBorderImage);
+ if (t != d->verticalTileMode) {
+ d->verticalTileMode = t;
+ emit verticalTileModeChanged();
+ update();
+ }
+}
+
+void QDeclarativeBorderImage::setGridScaledImage(const QDeclarativeGridScaledImage& sci)
+{
+ Q_D(QDeclarativeBorderImage);
+ if (!sci.isValid()) {
+ d->status = Error;
+ emit statusChanged(d->status);
+ } else {
+ QDeclarativeScaleGrid *sg = border();
+ sg->setTop(sci.gridTop());
+ sg->setBottom(sci.gridBottom());
+ sg->setLeft(sci.gridLeft());
+ sg->setRight(sci.gridRight());
+ d->horizontalTileMode = sci.horizontalTileRule();
+ d->verticalTileMode = sci.verticalTileRule();
+
+ d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl()));
+
+ QDeclarativePixmap::Options options;
+ if (d->async)
+ options |= QDeclarativePixmap::Asynchronous;
+ if (d->cache)
+ options |= QDeclarativePixmap::Cache;
+ d->pix.clear(this);
+ d->pix.load(qmlEngine(this), d->sciurl, options);
+
+ if (d->pix.isLoading()) {
+ static int thisRequestProgress = -1;
+ static int thisRequestFinished = -1;
+ if (thisRequestProgress == -1) {
+ thisRequestProgress =
+ QDeclarativeBorderImage::staticMetaObject.indexOfSlot("requestProgress(qint64,qint64)");
+ thisRequestFinished =
+ QDeclarativeBorderImage::staticMetaObject.indexOfSlot("requestFinished()");
+ }
+
+ d->pix.connectFinished(this, thisRequestFinished);
+ d->pix.connectDownloadProgress(this, thisRequestProgress);
+
+ } else {
+
+ QSize impsize = d->pix.implicitSize();
+ setImplicitWidth(impsize.width());
+ setImplicitHeight(impsize.height());
+
+ if (d->pix.isReady()) {
+ d->status = Ready;
+ } else {
+ d->status = Error;
+ qmlInfo(this) << d->pix.error();
+ }
+
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit progressChanged(1.0);
+ update();
+
+ }
+ }
+}
+
+void QDeclarativeBorderImage::requestFinished()
+{
+ Q_D(QDeclarativeBorderImage);
+
+ QSize impsize = d->pix.implicitSize();
+ if (d->pix.isError()) {
+ d->status = Error;
+ qmlInfo(this) << d->pix.error();
+ } else {
+ d->status = Ready;
+ }
+
+ setImplicitWidth(impsize.width());
+ setImplicitHeight(impsize.height());
+
+ if (d->sourcesize.width() != d->pix.width() || d->sourcesize.height() != d->pix.height())
+ emit sourceSizeChanged();
+
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit progressChanged(1.0);
+ update();
+}
+
+#define BORDERIMAGE_MAX_REDIRECT 16
+
+void QDeclarativeBorderImage::sciRequestFinished()
+{
+ Q_D(QDeclarativeBorderImage);
+
+ d->redirectCount++;
+ if (d->redirectCount < BORDERIMAGE_MAX_REDIRECT) {
+ QVariant redirect = d->sciReply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirect.isValid()) {
+ QUrl url = d->sciReply->url().resolved(redirect.toUrl());
+ setSource(url);
+ return;
+ }
+ }
+ d->redirectCount=0;
+
+ if (d->sciReply->error() != QNetworkReply::NoError) {
+ d->status = Error;
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ emit statusChanged(d->status);
+ } else {
+ QDeclarativeGridScaledImage sci(d->sciReply);
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ setGridScaledImage(sci);
+ }
+}
+
+void QDeclarativeBorderImage::doUpdate()
+{
+ update();
+}
+
+void QDeclarativeBorderImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ Q_D(QDeclarativeBorderImage);
+ if (d->pix.isNull() || d->width() <= 0.0 || d->height() <= 0.0)
+ return;
+
+ bool oldAA = p->testRenderHint(QPainter::Antialiasing);
+ bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform);
+ QTransform oldTransform;
+ if (d->smooth)
+ p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth);
+ if (d->mirror) {
+ oldTransform = p->transform();
+ QTransform mirror;
+ mirror.translate(d->width(), 0).scale(-1, 1.0);
+ p->setWorldTransform(mirror * oldTransform);
+ }
+
+ const QDeclarativeScaleGrid *border = d->getScaleGrid();
+ int left = border->left();
+ int right = border->right();
+ qreal borderWidth = left + right;
+ if (borderWidth > 0.0 && d->width() < borderWidth) {
+ qreal diff = borderWidth - d->width() - 1;
+ left -= qRound(diff * qreal(left) / borderWidth);
+ right -= qRound(diff * qreal(right) / borderWidth);
+ }
+ int top = border->top();
+ int bottom = border->bottom();
+ qreal borderHeight = top + bottom;
+ if (borderHeight > 0.0 && d->height() < borderHeight) {
+ qreal diff = borderHeight - d->height() - 1;
+ top -= qRound(diff * qreal(top) / borderHeight);
+ bottom -= qRound(diff * qreal(bottom) / borderHeight);
+ }
+ QMargins margins(left, top, right, bottom);
+ QTileRules rules((Qt::TileRule)d->horizontalTileMode, (Qt::TileRule)d->verticalTileMode);
+ qDrawBorderPixmap(p, QRect(0, 0, (int)d->width(), (int)d->height()), margins, d->pix, d->pix.rect(), margins, rules);
+ if (d->smooth) {
+ p->setRenderHint(QPainter::Antialiasing, oldAA);
+ p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
+ }
+ if (d->mirror)
+ p->setWorldTransform(oldTransform);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage_p.h b/src/declarative/graphicsitems/qdeclarativeborderimage_p.h
new file mode 100644
index 00000000..3db573c8
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeborderimage_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEBORDERIMAGE_H
+#define QDECLARATIVEBORDERIMAGE_H
+
+#include "private/qdeclarativeimagebase_p.h"
+
+#include <QtNetwork/qnetworkreply.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeScaleGrid;
+class QDeclarativeGridScaledImage;
+class QDeclarativeBorderImagePrivate;
+class Q_AUTOTEST_EXPORT QDeclarativeBorderImage : public QDeclarativeImageBase
+{
+ Q_OBJECT
+ Q_ENUMS(TileMode)
+
+ Q_PROPERTY(QDeclarativeScaleGrid *border READ border CONSTANT)
+ Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged)
+ Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged)
+
+public:
+ QDeclarativeBorderImage(QDeclarativeItem *parent=0);
+ ~QDeclarativeBorderImage();
+
+ QDeclarativeScaleGrid *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 paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+ void setSource(const QUrl &url);
+
+ void setSourceSize(const QSize&);
+
+Q_SIGNALS:
+ void horizontalTileModeChanged();
+ void verticalTileModeChanged();
+
+protected:
+ virtual void load();
+
+private:
+ void setGridScaledImage(const QDeclarativeGridScaledImage& sci);
+
+private Q_SLOTS:
+ void doUpdate();
+ void requestFinished();
+ void sciRequestFinished();
+
+private:
+ Q_DISABLE_COPY(QDeclarativeBorderImage)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeBorderImage)
+};
+
+QT_END_NAMESPACE
+QML_DECLARE_TYPE(QDeclarativeBorderImage)
+QT_END_HEADER
+
+#endif // QDECLARATIVEBORDERIMAGE_H
diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage_p_p.h b/src/declarative/graphicsitems/qdeclarativeborderimage_p_p.h
new file mode 100644
index 00000000..872175f4
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeborderimage_p_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEBORDERIMAGE_P_H
+#define QDECLARATIVEBORDERIMAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeimagebase_p_p.h"
+#include "private/qdeclarativescalegrid_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkReply;
+class QDeclarativeBorderImagePrivate : public QDeclarativeImageBasePrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarativeBorderImage)
+
+public:
+ QDeclarativeBorderImagePrivate()
+ : border(0), sciReply(0),
+ horizontalTileMode(QDeclarativeBorderImage::Stretch),
+ verticalTileMode(QDeclarativeBorderImage::Stretch),
+ redirectCount(0)
+ {
+ }
+
+ ~QDeclarativeBorderImagePrivate()
+ {
+ }
+
+
+ QDeclarativeScaleGrid *getScaleGrid()
+ {
+ Q_Q(QDeclarativeBorderImage);
+ if (!border) {
+ border = new QDeclarativeScaleGrid(q);
+ static int borderChangedSignalIdx = -1;
+ static int doUpdateSlotIdx = -1;
+ if (borderChangedSignalIdx < 0)
+ borderChangedSignalIdx = QDeclarativeScaleGrid::staticMetaObject.indexOfSignal("borderChanged()");
+ if (doUpdateSlotIdx < 0)
+ doUpdateSlotIdx = QDeclarativeBorderImage::staticMetaObject.indexOfSlot("doUpdate()");
+ QMetaObject::connect(border, borderChangedSignalIdx, q, doUpdateSlotIdx);
+ }
+ return border;
+ }
+
+ QDeclarativeScaleGrid *border;
+ QUrl sciurl;
+ QNetworkReply *sciReply;
+ QDeclarativeBorderImage::TileMode horizontalTileMode;
+ QDeclarativeBorderImage::TileMode verticalTileMode;
+ int redirectCount;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEBORDERIMAGE_P_H
diff --git a/src/declarative/graphicsitems/qdeclarativeevents.cpp b/src/declarative/graphicsitems/qdeclarativeevents.cpp
new file mode 100644
index 00000000..59f82f67
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeevents.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativeevents_p_p.h"
+
+QT_BEGIN_NAMESPACE
+/*!
+ \qmlclass KeyEvent QDeclarativeKeyEvent
+ \since 4.7
+ \ingroup qml-event-elements
+
+ \brief The KeyEvent object provides information about a key event.
+
+ For example, the following changes the Item's state property when the Enter
+ key is pressed:
+ \qml
+Item {
+ focus: true
+ Keys.onPressed: { if (event.key == Qt.Key_Enter) state = 'ShowDetails'; }
+}
+ \endqml
+*/
+
+/*!
+ \qmlproperty int KeyEvent::key
+
+ This property holds the code of the key that was pressed or released.
+
+ See \l {Qt::Key}{Qt.Key} for the list of keyboard codes. These codes are
+ independent of the underlying window system. Note that this
+ function does not distinguish between capital and non-capital
+ letters, use the text() function (returning the Unicode text the
+ key generated) for this purpose.
+
+ A value of either 0 or \l {Qt::Key_unknown}{Qt.Key_Unknown} means that the event is not
+ the result of a known key; for example, it may be the result of
+ a compose sequence, a keyboard macro, or due to key event
+ compression.
+*/
+
+/*!
+ \qmlproperty string KeyEvent::text
+
+ This property holds the Unicode text that the key generated.
+ The text returned can be an empty string in cases where modifier keys,
+ such as Shift, Control, Alt, and Meta, are being pressed or released.
+ In such cases \c key will contain a valid value
+*/
+
+/*!
+ \qmlproperty bool KeyEvent::isAutoRepeat
+
+ This property holds whether this event comes from an auto-repeating key.
+*/
+
+/*!
+ \qmlproperty int KeyEvent::count
+
+ This property holds the number of keys involved in this event. If \l KeyEvent::text
+ is not empty, this is simply the length of the string.
+*/
+
+/*!
+ \qmlproperty bool KeyEvent::accepted
+
+ Setting \a accepted to true prevents the key event from being
+ propagated to the item's parent.
+
+ Generally, if the item acts on the key event then it should be accepted
+ so that ancestor items do not also respond to the same event.
+*/
+
+/*!
+ \qmlproperty int KeyEvent::modifiers
+
+ This property holds the keyboard modifier flags that existed immediately
+ before the event occurred.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.NoModifier - No modifier key is pressed.
+ \o Qt.ShiftModifier - A Shift key on the keyboard is pressed.
+ \o Qt.ControlModifier - A Ctrl key on the keyboard is pressed.
+ \o Qt.AltModifier - An Alt key on the keyboard is pressed.
+ \o Qt.MetaModifier - A Meta key on the keyboard is pressed.
+ \o Qt.KeypadModifier - A keypad button is pressed.
+ \endlist
+
+ For example, to react to a Shift key + Enter key combination:
+ \qml
+ Item {
+ focus: true
+ Keys.onPressed: {
+ if ((event.key == Qt.Key_Enter) && (event.modifiers & Qt.ShiftModifier))
+ doSomething();
+ }
+ }
+ \endqml
+*/
+
+
+/*!
+ \qmlclass MouseEvent QDeclarativeMouseEvent
+ \since 4.7
+ \ingroup qml-event-elements
+
+ \brief The MouseEvent object provides information about a mouse event.
+
+ The position of the mouse can be found via the \l x and \l y properties.
+ The button that caused the event is available via the \l button property.
+
+ \sa MouseArea
+*/
+
+/*!
+ \internal
+ \class QDeclarativeMouseEvent
+*/
+
+/*!
+ \qmlproperty int MouseEvent::x
+ \qmlproperty int MouseEvent::y
+
+ These properties hold the coordinates of the position supplied by the mouse event.
+*/
+
+
+/*!
+ \qmlproperty bool MouseEvent::accepted
+
+ Setting \a accepted to true prevents the mouse event from being
+ propagated to items below this item.
+
+ Generally, if the item acts on the mouse event then it should be accepted
+ so that items lower in the stacking order do not also respond to the same event.
+*/
+
+/*!
+ \qmlproperty enumeration MouseEvent::button
+
+ This property holds the button that caused the event. It can be one of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MiddleButton
+ \endlist
+*/
+
+/*!
+ \qmlproperty bool MouseEvent::wasHeld
+
+ This property is true if the mouse button has been held pressed longer the
+ threshold (800ms).
+*/
+
+/*!
+ \qmlproperty int MouseEvent::buttons
+
+ This property holds the mouse buttons pressed when the event was generated.
+ For mouse move events, this is all buttons that are pressed down. For mouse
+ press and double click events this includes the button that caused the event.
+ For mouse release events this excludes the button that caused the event.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MiddleButton
+ \endlist
+*/
+
+/*!
+ \qmlproperty int MouseEvent::modifiers
+
+ This property holds the keyboard modifier flags that existed immediately
+ before the event occurred.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.NoModifier - No modifier key is pressed.
+ \o Qt.ShiftModifier - A Shift key on the keyboard is pressed.
+ \o Qt.ControlModifier - A Ctrl key on the keyboard is pressed.
+ \o Qt.AltModifier - An Alt key on the keyboard is pressed.
+ \o Qt.MetaModifier - A Meta key on the keyboard is pressed.
+ \o Qt.KeypadModifier - A keypad button is pressed.
+ \endlist
+
+ For example, to react to a Shift key + Left mouse button click:
+ \qml
+ MouseArea {
+ onClicked: {
+ if ((mouse.button == Qt.LeftButton) && (mouse.modifiers & Qt.ShiftModifier))
+ doSomething();
+ }
+ }
+ \endqml
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativeevents_p_p.h b/src/declarative/graphicsitems/qdeclarativeevents_p_p.h
new file mode 100644
index 00000000..b9a2b55f
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeevents_p_p.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEEVENTS_P_H
+#define QDECLARATIVEEVENTS_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 QDeclarativeKeyEvent : 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:
+ QDeclarativeKeyEvent(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); }
+ QDeclarativeKeyEvent(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;
+};
+
+class QDeclarativeMouseEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int x READ x)
+ Q_PROPERTY(int 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:
+ QDeclarativeMouseEvent(int x, int 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) {}
+
+ int x() const { return _x; }
+ int 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(int x) { _x = x; }
+ void setY(int y) { _y = y; }
+
+ bool isAccepted() { return _accepted; }
+ void setAccepted(bool accepted) { _accepted = accepted; }
+
+private:
+ int _x;
+ int _y;
+ Qt::MouseButton _button;
+ Qt::MouseButtons _buttons;
+ Qt::KeyboardModifiers _modifiers;
+ bool _wasHeld;
+ bool _isClick;
+ bool _accepted;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeKeyEvent)
+QML_DECLARE_TYPE(QDeclarativeMouseEvent)
+
+#endif // QDECLARATIVEEVENTS_P_H
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp
new file mode 100644
index 00000000..229d04bd
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp
@@ -0,0 +1,1805 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativeflickable_p.h"
+#include "private/qdeclarativeflickable_p_p.h"
+#include <qdeclarativeinfo.h>
+#include <QGraphicsSceneMouseEvent>
+#include <QPointer>
+#include <QTimer>
+#include "qplatformdefs.h"
+
+QT_BEGIN_NAMESPACE
+
+// The maximum number of pixels a flick can overshoot
+#ifndef QML_FLICK_OVERSHOOT
+#define QML_FLICK_OVERSHOOT 200
+#endif
+
+// The number of samples to use in calculating the velocity of a flick
+#ifndef QML_FLICK_SAMPLEBUFFER
+#define QML_FLICK_SAMPLEBUFFER 3
+#endif
+
+// The number of samples to discard when calculating the flick velocity.
+// Touch panels often produce inaccurate results as the finger is lifted.
+#ifndef QML_FLICK_DISCARDSAMPLES
+#define QML_FLICK_DISCARDSAMPLES 1
+#endif
+
+// The default maximum velocity of a flick.
+#ifndef QML_FLICK_DEFAULTMAXVELOCITY
+#define QML_FLICK_DEFAULTMAXVELOCITY 2500
+#endif
+
+// The default deceleration of a flick.
+#ifndef QML_FLICK_DEFAULTDECELERATION
+#define QML_FLICK_DEFAULTDECELERATION 1750
+#endif
+
+// How much faster to decelerate when overshooting
+#ifndef QML_FLICK_OVERSHOOTFRICTION
+#define QML_FLICK_OVERSHOOTFRICTION 8
+#endif
+
+// FlickThreshold determines how far the "mouse" must have moved
+// before we perform a flick.
+static const int FlickThreshold = 20;
+
+// RetainGrabVelocity is the maxmimum instantaneous velocity that
+// will ensure the Flickable retains the grab on consecutive flicks.
+static const int RetainGrabVelocity = 15;
+
+QDeclarativeFlickableVisibleArea::QDeclarativeFlickableVisibleArea(QDeclarativeFlickable *parent)
+ : QObject(parent), flickable(parent), m_xPosition(0.), m_widthRatio(0.)
+ , m_yPosition(0.), m_heightRatio(0.)
+{
+}
+
+qreal QDeclarativeFlickableVisibleArea::widthRatio() const
+{
+ return m_widthRatio;
+}
+
+qreal QDeclarativeFlickableVisibleArea::xPosition() const
+{
+ return m_xPosition;
+}
+
+qreal QDeclarativeFlickableVisibleArea::heightRatio() const
+{
+ return m_heightRatio;
+}
+
+qreal QDeclarativeFlickableVisibleArea::yPosition() const
+{
+ return m_yPosition;
+}
+
+void QDeclarativeFlickableVisibleArea::updateVisible()
+{
+ QDeclarativeFlickablePrivate *p = static_cast<QDeclarativeFlickablePrivate *>(QGraphicsItemPrivate::get(flickable));
+
+ bool changeX = false;
+ bool changeY = false;
+ bool changeWidth = false;
+ bool changeHeight = false;
+
+ // Vertical
+ const qreal viewheight = flickable->height();
+ const qreal maxyextent = -flickable->maxYExtent() + flickable->minYExtent();
+ qreal pagePos = (-p->vData.move.value() + flickable->minYExtent()) / (maxyextent + viewheight);
+ qreal pageSize = viewheight / (maxyextent + viewheight);
+
+ if (pageSize != m_heightRatio) {
+ m_heightRatio = pageSize;
+ changeHeight = true;
+ }
+ if (pagePos != m_yPosition) {
+ m_yPosition = pagePos;
+ changeY = true;
+ }
+
+ // Horizontal
+ const qreal viewwidth = flickable->width();
+ const qreal maxxextent = -flickable->maxXExtent() + flickable->minXExtent();
+ pagePos = (-p->hData.move.value() + flickable->minXExtent()) / (maxxextent + viewwidth);
+ pageSize = viewwidth / (maxxextent + viewwidth);
+
+ if (pageSize != m_widthRatio) {
+ m_widthRatio = pageSize;
+ changeWidth = true;
+ }
+ if (pagePos != m_xPosition) {
+ m_xPosition = pagePos;
+ changeX = true;
+ }
+
+ if (changeX)
+ emit xPositionChanged(m_xPosition);
+ if (changeY)
+ emit yPositionChanged(m_yPosition);
+ if (changeWidth)
+ emit widthRatioChanged(m_widthRatio);
+ if (changeHeight)
+ emit heightRatioChanged(m_heightRatio);
+}
+
+
+QDeclarativeFlickablePrivate::QDeclarativeFlickablePrivate()
+ : contentItem(new QDeclarativeItem)
+ , hData(this, &QDeclarativeFlickablePrivate::setRoundedViewportX)
+ , vData(this, &QDeclarativeFlickablePrivate::setRoundedViewportY)
+ , hMoved(false), vMoved(false)
+ , stealMouse(false), pressed(false), interactive(true), calcVelocity(false)
+ , deceleration(QML_FLICK_DEFAULTDECELERATION)
+ , maxVelocity(QML_FLICK_DEFAULTMAXVELOCITY), reportedVelocitySmoothing(100)
+ , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(400)
+ , fixupMode(Normal), vTime(0), visibleArea(0)
+ , flickableDirection(QDeclarativeFlickable::AutoFlickDirection)
+ , boundsBehavior(QDeclarativeFlickable::DragAndOvershootBounds)
+{
+}
+
+void QDeclarativeFlickablePrivate::init()
+{
+ Q_Q(QDeclarativeFlickable);
+ QDeclarative_setParent_noEvent(contentItem, q);
+ contentItem->setParentItem(q);
+ static int timelineUpdatedIdx = -1;
+ static int timelineCompletedIdx = -1;
+ static int flickableTickedIdx = -1;
+ static int flickableMovementEndingIdx = -1;
+ if (timelineUpdatedIdx == -1) {
+ timelineUpdatedIdx = QDeclarativeTimeLine::staticMetaObject.indexOfSignal("updated()");
+ timelineCompletedIdx = QDeclarativeTimeLine::staticMetaObject.indexOfSignal("completed()");
+ flickableTickedIdx = QDeclarativeFlickable::staticMetaObject.indexOfSlot("ticked()");
+ flickableMovementEndingIdx = QDeclarativeFlickable::staticMetaObject.indexOfSlot("movementEnding()");
+ }
+ QMetaObject::connect(&timeline, timelineUpdatedIdx,
+ q, flickableTickedIdx, Qt::DirectConnection);
+ QMetaObject::connect(&timeline, timelineCompletedIdx,
+ q, flickableMovementEndingIdx, Qt::DirectConnection);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFiltersChildEvents(true);
+ QDeclarativeItemPrivate *viewportPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(contentItem));
+ viewportPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ lastPosTime.invalidate();
+}
+
+/*
+ Returns the amount to overshoot by given a view size.
+ Will be up to the lesser of 1/3 of the view size or QML_FLICK_OVERSHOOT
+*/
+qreal QDeclarativeFlickablePrivate::overShootDistance(qreal size)
+{
+ if (maxVelocity <= 0)
+ return 0.0;
+
+ return qMin(qreal(QML_FLICK_OVERSHOOT), size/3);
+}
+
+void QDeclarativeFlickablePrivate::AxisData::addVelocitySample(qreal v, qreal maxVelocity)
+{
+ if (v > maxVelocity)
+ v = maxVelocity;
+ else if (v < -maxVelocity)
+ v = -maxVelocity;
+ velocityBuffer.append(v);
+ if (velocityBuffer.count() > QML_FLICK_SAMPLEBUFFER)
+ velocityBuffer.remove(0);
+}
+
+void QDeclarativeFlickablePrivate::AxisData::updateVelocity()
+{
+ velocity = 0;
+ if (velocityBuffer.count() > QML_FLICK_DISCARDSAMPLES) {
+ int count = velocityBuffer.count()-QML_FLICK_DISCARDSAMPLES;
+ for (int i = 0; i < count; ++i) {
+ qreal v = velocityBuffer.at(i);
+ velocity += v;
+ }
+ velocity /= count;
+ }
+}
+
+void QDeclarativeFlickablePrivate::itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeom, const QRectF &oldGeom)
+{
+ Q_Q(QDeclarativeFlickable);
+ if (item == contentItem) {
+ if (newGeom.x() != oldGeom.x())
+ emit q->contentXChanged();
+ if (newGeom.y() != oldGeom.y())
+ emit q->contentYChanged();
+ }
+}
+
+void QDeclarativeFlickablePrivate::flickX(qreal velocity)
+{
+ Q_Q(QDeclarativeFlickable);
+ flick(hData, q->minXExtent(), q->maxXExtent(), q->width(), fixupX_callback, velocity);
+}
+
+void QDeclarativeFlickablePrivate::flickY(qreal velocity)
+{
+ Q_Q(QDeclarativeFlickable);
+ flick(vData, q->minYExtent(), q->maxYExtent(), q->height(), fixupY_callback, velocity);
+}
+
+void QDeclarativeFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal,
+ QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity)
+{
+ Q_Q(QDeclarativeFlickable);
+ qreal maxDistance = -1;
+ data.fixingUp = false;
+ // -ve velocity means list is moving up
+ if (velocity > 0) {
+ maxDistance = qAbs(minExtent - data.move.value());
+ data.flickTarget = minExtent;
+ } else {
+ maxDistance = qAbs(maxExtent - data.move.value());
+ data.flickTarget = maxExtent;
+ }
+ if (maxDistance > 0) {
+ qreal v = velocity;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ timeline.reset(data.move);
+ if (boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds)
+ timeline.accel(data.move, v, deceleration);
+ else
+ timeline.accel(data.move, v, deceleration, maxDistance);
+ timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this));
+ if (!hData.flicking && q->xflick()) {
+ hData.flicking = true;
+ emit q->flickingChanged();
+ emit q->flickingHorizontallyChanged();
+ if (!vData.flicking)
+ emit q->flickStarted();
+ }
+ if (!vData.flicking && q->yflick()) {
+ vData.flicking = true;
+ emit q->flickingChanged();
+ emit q->flickingVerticallyChanged();
+ if (!hData.flicking)
+ emit q->flickStarted();
+ }
+ } else {
+ timeline.reset(data.move);
+ fixup(data, minExtent, maxExtent);
+ }
+}
+
+void QDeclarativeFlickablePrivate::fixupY_callback(void *data)
+{
+ ((QDeclarativeFlickablePrivate *)data)->fixupY();
+}
+
+void QDeclarativeFlickablePrivate::fixupX_callback(void *data)
+{
+ ((QDeclarativeFlickablePrivate *)data)->fixupX();
+}
+
+void QDeclarativeFlickablePrivate::fixupX()
+{
+ Q_Q(QDeclarativeFlickable);
+ fixup(hData, q->minXExtent(), q->maxXExtent());
+}
+
+void QDeclarativeFlickablePrivate::fixupY()
+{
+ Q_Q(QDeclarativeFlickable);
+ fixup(vData, q->minYExtent(), q->maxYExtent());
+}
+
+void QDeclarativeFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
+{
+ if (data.move.value() > minExtent || maxExtent > minExtent) {
+ timeline.reset(data.move);
+ if (data.move.value() != minExtent) {
+ switch (fixupMode) {
+ case Immediate:
+ timeline.set(data.move, minExtent);
+ break;
+ case ExtentChanged:
+ // The target has changed. Don't start from the beginning; just complete the
+ // second half of the animation using the new extent.
+ timeline.move(data.move, minExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4);
+ data.fixingUp = true;
+ break;
+ default: {
+ qreal dist = minExtent - data.move;
+ timeline.move(data.move, minExtent - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4);
+ timeline.move(data.move, minExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4);
+ data.fixingUp = true;
+ }
+ }
+ }
+ } else if (data.move.value() < maxExtent) {
+ timeline.reset(data.move);
+ switch (fixupMode) {
+ case Immediate:
+ timeline.set(data.move, maxExtent);
+ break;
+ case ExtentChanged:
+ // The target has changed. Don't start from the beginning; just complete the
+ // second half of the animation using the new extent.
+ timeline.move(data.move, maxExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4);
+ data.fixingUp = true;
+ break;
+ default: {
+ qreal dist = maxExtent - data.move;
+ timeline.move(data.move, maxExtent - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4);
+ timeline.move(data.move, maxExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4);
+ data.fixingUp = true;
+ }
+ }
+ }
+ data.inOvershoot = false;
+ fixupMode = Normal;
+ vTime = timeline.time();
+}
+
+void QDeclarativeFlickablePrivate::updateBeginningEnd()
+{
+ Q_Q(QDeclarativeFlickable);
+ bool atBoundaryChange = false;
+
+ // Vertical
+ const int maxyextent = int(-q->maxYExtent());
+ const qreal ypos = -vData.move.value();
+ bool atBeginning = (ypos <= -q->minYExtent());
+ bool atEnd = (maxyextent <= ypos);
+
+ if (atBeginning != vData.atBeginning) {
+ vData.atBeginning = atBeginning;
+ atBoundaryChange = true;
+ }
+ if (atEnd != vData.atEnd) {
+ vData.atEnd = atEnd;
+ atBoundaryChange = true;
+ }
+
+ // Horizontal
+ const int maxxextent = int(-q->maxXExtent());
+ const qreal xpos = -hData.move.value();
+ atBeginning = (xpos <= -q->minXExtent());
+ atEnd = (maxxextent <= xpos);
+
+ if (atBeginning != hData.atBeginning) {
+ hData.atBeginning = atBeginning;
+ atBoundaryChange = true;
+ }
+ if (atEnd != hData.atEnd) {
+ hData.atEnd = atEnd;
+ atBoundaryChange = true;
+ }
+
+ if (atBoundaryChange)
+ emit q->isAtBoundaryChanged();
+
+ if (visibleArea)
+ visibleArea->updateVisible();
+}
+
+/*!
+ \qmlclass Flickable QDeclarativeFlickable
+ \since 4.7
+ \ingroup qml-basic-interaction-elements
+
+ \brief The Flickable item provides a surface that can be "flicked".
+ \inherits Item
+
+ The Flickable item places its children on a surface that can be dragged
+ and flicked, causing the view onto the child items to scroll. This
+ behavior forms the basis of Items that are designed to show large numbers
+ of child items, such as \l ListView and \l GridView.
+
+ In traditional user interfaces, views can be scrolled using standard
+ controls, such as scroll bars and arrow buttons. In some situations, it
+ is also possible to drag the view directly by pressing and holding a
+ mouse button while moving the cursor. In touch-based user interfaces,
+ this dragging action is often complemented with a flicking action, where
+ scrolling continues after the user has stopped touching the view.
+
+ Flickable does not automatically clip its contents. If it is not used as
+ a full-screen item, you should consider setting the \l{Item::}{clip} property
+ to true.
+
+ \section1 Example Usage
+
+ \div {class="float-right"}
+ \inlineimage flickable.gif
+ \enddiv
+
+ The following example shows a small view onto a large image in which the
+ user can drag or flick the image in order to view different parts of it.
+
+ \snippet doc/src/snippets/declarative/flickable.qml document
+
+ \clearfloat
+
+ Items declared as children of a Flickable are automatically parented to the
+ Flickable's \l contentItem. This should be taken into account when
+ operating on the children of the Flickable; it is usually the children of
+ \c contentItem that are relevant. For example, the bound of Items added
+ to the Flickable will be available by \c contentItem.childrenRect
+
+ \section1 Limitations
+
+ \note Due to an implementation detail, items placed inside a Flickable cannot anchor to it by
+ \c id. Use \c parent instead.
+*/
+
+/*!
+ \qmlsignal Flickable::onMovementStarted()
+
+ This handler is called when the view begins moving due to user
+ interaction.
+*/
+
+/*!
+ \qmlsignal Flickable::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 Flickable::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 Flickable::onFlickEnded()
+
+ This handler is called when the view stops moving due to a flick.
+*/
+
+/*!
+ \qmlproperty real Flickable::visibleArea.xPosition
+ \qmlproperty real Flickable::visibleArea.widthRatio
+ \qmlproperty real Flickable::visibleArea.yPosition
+ \qmlproperty real Flickable::visibleArea.heightRatio
+
+ These properties describe the position and size of the currently viewed area.
+ The size is defined as the percentage of the full view currently visible,
+ scaled to 0.0 - 1.0. The page position is usually in the range 0.0 (beginning) to
+ 1.0 minus size ratio (end), i.e. \c yPosition is in the range 0.0 to 1.0-\c heightRatio.
+ However, it is possible for the contents to be dragged outside of the normal
+ range, resulting in the page positions also being outside the normal range.
+
+ These properties are typically used to draw a scrollbar. For example:
+
+ \snippet doc/src/snippets/declarative/flickableScrollbar.qml 0
+ \dots 8
+ \snippet doc/src/snippets/declarative/flickableScrollbar.qml 1
+
+ \sa {declarative/ui-components/scrollbar}{scrollbar example}
+*/
+
+QDeclarativeFlickable::QDeclarativeFlickable(QDeclarativeItem *parent)
+ : QDeclarativeItem(*(new QDeclarativeFlickablePrivate), parent)
+{
+ Q_D(QDeclarativeFlickable);
+ d->init();
+}
+
+QDeclarativeFlickable::QDeclarativeFlickable(QDeclarativeFlickablePrivate &dd, QDeclarativeItem *parent)
+ : QDeclarativeItem(dd, parent)
+{
+ Q_D(QDeclarativeFlickable);
+ d->init();
+}
+
+QDeclarativeFlickable::~QDeclarativeFlickable()
+{
+}
+
+/*!
+ \qmlproperty real Flickable::contentX
+ \qmlproperty real Flickable::contentY
+
+ These properties hold the surface coordinate currently at the top-left
+ corner of the Flickable. For example, if you flick an image up 100 pixels,
+ \c contentY will be 100.
+*/
+qreal QDeclarativeFlickable::contentX() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return -d->contentItem->x();
+}
+
+void QDeclarativeFlickable::setContentX(qreal pos)
+{
+ Q_D(QDeclarativeFlickable);
+ d->timeline.reset(d->hData.move);
+ d->vTime = d->timeline.time();
+ movementXEnding();
+ if (-pos != d->hData.move.value()) {
+ d->hData.move.setValue(-pos);
+ viewportMoved();
+ }
+}
+
+qreal QDeclarativeFlickable::contentY() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return -d->contentItem->y();
+}
+
+void QDeclarativeFlickable::setContentY(qreal pos)
+{
+ Q_D(QDeclarativeFlickable);
+ d->timeline.reset(d->vData.move);
+ d->vTime = d->timeline.time();
+ movementYEnding();
+ if (-pos != d->vData.move.value()) {
+ d->vData.move.setValue(-pos);
+ viewportMoved();
+ }
+}
+
+/*!
+ \qmlproperty bool Flickable::interactive
+
+ This property describes whether the user can interact with the Flickable.
+ A user cannot drag or flick a Flickable that is not interactive.
+
+ By default, this property is true.
+
+ This property is useful for temporarily disabling flicking. This allows
+ special interaction with Flickable's children; for example, you might want
+ to freeze a flickable map while scrolling through a pop-up dialog that
+ is a child of the Flickable.
+*/
+bool QDeclarativeFlickable::isInteractive() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->interactive;
+}
+
+void QDeclarativeFlickable::setInteractive(bool interactive)
+{
+ Q_D(QDeclarativeFlickable);
+ if (interactive != d->interactive) {
+ d->interactive = interactive;
+ if (!interactive && (d->hData.flicking || d->vData.flicking)) {
+ d->timeline.clear();
+ d->vTime = d->timeline.time();
+ d->hData.flicking = false;
+ d->vData.flicking = false;
+ emit flickingChanged();
+ emit flickingHorizontallyChanged();
+ emit flickingVerticallyChanged();
+ emit flickEnded();
+ }
+ emit interactiveChanged();
+ }
+}
+
+/*!
+ \qmlproperty real Flickable::horizontalVelocity
+ \qmlproperty real Flickable::verticalVelocity
+
+ The instantaneous velocity of movement along the x and y axes, in pixels/sec.
+
+ The reported velocity is smoothed to avoid erratic output.
+*/
+qreal QDeclarativeFlickable::horizontalVelocity() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->hData.smoothVelocity.value();
+}
+
+qreal QDeclarativeFlickable::verticalVelocity() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->vData.smoothVelocity.value();
+}
+
+/*!
+ \qmlproperty bool Flickable::atXBeginning
+ \qmlproperty bool Flickable::atXEnd
+ \qmlproperty bool Flickable::atYBeginning
+ \qmlproperty bool Flickable::atYEnd
+
+ These properties are true if the flickable view is positioned at the beginning,
+ or end respecively.
+*/
+bool QDeclarativeFlickable::isAtXEnd() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->hData.atEnd;
+}
+
+bool QDeclarativeFlickable::isAtXBeginning() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->hData.atBeginning;
+}
+
+bool QDeclarativeFlickable::isAtYEnd() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->vData.atEnd;
+}
+
+bool QDeclarativeFlickable::isAtYBeginning() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->vData.atBeginning;
+}
+
+void QDeclarativeFlickable::ticked()
+{
+ viewportMoved();
+}
+
+/*!
+ \qmlproperty Item Flickable::contentItem
+
+ The internal item that contains the Items to be moved in the Flickable.
+
+ Items declared as children of a Flickable are automatically parented to the Flickable's contentItem.
+
+ Items created dynamically need to be explicitly parented to the \e contentItem:
+ \code
+ Flickable {
+ id: myFlickable
+ function addItem(file) {
+ var component = Qt.createComponent(file)
+ component.createObject(myFlickable.contentItem);
+ }
+ }
+ \endcode
+*/
+QDeclarativeItem *QDeclarativeFlickable::contentItem()
+{
+ Q_D(QDeclarativeFlickable);
+ return d->contentItem;
+}
+
+QDeclarativeFlickableVisibleArea *QDeclarativeFlickable::visibleArea()
+{
+ Q_D(QDeclarativeFlickable);
+ if (!d->visibleArea)
+ d->visibleArea = new QDeclarativeFlickableVisibleArea(this);
+ return d->visibleArea;
+}
+
+/*!
+ \qmlproperty enumeration Flickable::flickableDirection
+
+ This property determines which directions the view can be flicked.
+
+ \list
+ \o Flickable.AutoFlickDirection (default) - allows flicking vertically if the
+ \e contentHeight is not equal to the \e height of the Flickable.
+ Allows flicking horizontally if the \e contentWidth is not equal
+ to the \e width of the Flickable.
+ \o Flickable.HorizontalFlick - allows flicking horizontally.
+ \o Flickable.VerticalFlick - allows flicking vertically.
+ \o Flickable.HorizontalAndVerticalFlick - allows flicking in both directions.
+ \endlist
+*/
+QDeclarativeFlickable::FlickableDirection QDeclarativeFlickable::flickableDirection() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->flickableDirection;
+}
+
+void QDeclarativeFlickable::setFlickableDirection(FlickableDirection direction)
+{
+ Q_D(QDeclarativeFlickable);
+ if (direction != d->flickableDirection) {
+ d->flickableDirection = direction;
+ emit flickableDirectionChanged();
+ }
+}
+
+void QDeclarativeFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QDeclarativeFlickable);
+ if (interactive && timeline.isActive()
+ && (qAbs(hData.smoothVelocity.value()) > RetainGrabVelocity || qAbs(vData.smoothVelocity.value()) > RetainGrabVelocity))
+ stealMouse = true; // If we've been flicked then steal the click.
+ else
+ stealMouse = false;
+ q->setKeepMouseGrab(stealMouse);
+ pressed = true;
+ timeline.clear();
+ hData.reset();
+ vData.reset();
+ hData.dragMinBound = q->minXExtent();
+ vData.dragMinBound = q->minYExtent();
+ hData.dragMaxBound = q->maxXExtent();
+ vData.dragMaxBound = q->maxYExtent();
+ fixupMode = Normal;
+ lastPos = QPoint();
+ QDeclarativeItemPrivate::start(lastPosTime);
+ pressPos = event->pos();
+ hData.pressPos = hData.move.value();
+ vData.pressPos = vData.move.value();
+ hData.flicking = false;
+ vData.flicking = false;
+ QDeclarativeItemPrivate::start(pressTime);
+ QDeclarativeItemPrivate::start(velocityTime);
+}
+
+void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QDeclarativeFlickable);
+ if (!interactive || !lastPosTime.isValid())
+ return;
+ bool rejectY = false;
+ bool rejectX = false;
+
+ bool stealY = stealMouse;
+ bool stealX = stealMouse;
+
+ if (q->yflick()) {
+ int dy = int(event->pos().y() - pressPos.y());
+ if (qAbs(dy) > QApplication::startDragDistance() || QDeclarativeItemPrivate::elapsed(pressTime) > 200) {
+ if (!vMoved)
+ vData.dragStartOffset = dy;
+ qreal newY = dy + vData.pressPos - vData.dragStartOffset;
+ const qreal minY = vData.dragMinBound;
+ const qreal maxY = vData.dragMaxBound;
+ if (newY > minY)
+ newY = minY + (newY - minY) / 2;
+ if (newY < maxY && maxY - minY <= 0)
+ newY = maxY + (newY - maxY) / 2;
+ if (boundsBehavior == QDeclarativeFlickable::StopAtBounds && (newY > minY || newY < maxY)) {
+ rejectY = true;
+ if (newY < maxY) {
+ newY = maxY;
+ rejectY = false;
+ }
+ if (newY > minY) {
+ newY = minY;
+ rejectY = false;
+ }
+ }
+ if (!rejectY && stealMouse) {
+ vData.move.setValue(qRound(newY));
+ vMoved = true;
+ }
+ if (qAbs(dy) > QApplication::startDragDistance())
+ stealY = true;
+ }
+ }
+
+ if (q->xflick()) {
+ int dx = int(event->pos().x() - pressPos.x());
+ if (qAbs(dx) > QApplication::startDragDistance() || QDeclarativeItemPrivate::elapsed(pressTime) > 200) {
+ if (!hMoved)
+ hData.dragStartOffset = dx;
+ qreal newX = dx + hData.pressPos - hData.dragStartOffset;
+ const qreal minX = hData.dragMinBound;
+ const qreal maxX = hData.dragMaxBound;
+ if (newX > minX)
+ newX = minX + (newX - minX) / 2;
+ if (newX < maxX && maxX - minX <= 0)
+ newX = maxX + (newX - maxX) / 2;
+ if (boundsBehavior == QDeclarativeFlickable::StopAtBounds && (newX > minX || newX < maxX)) {
+ rejectX = true;
+ if (newX < maxX) {
+ newX = maxX;
+ rejectX = false;
+ }
+ if (newX > minX) {
+ newX = minX;
+ rejectX = false;
+ }
+ }
+ if (!rejectX && stealMouse) {
+ hData.move.setValue(qRound(newX));
+ hMoved = true;
+ }
+
+ if (qAbs(dx) > QApplication::startDragDistance())
+ stealX = true;
+ }
+ }
+
+ stealMouse = stealX || stealY;
+ if (stealMouse)
+ q->setKeepMouseGrab(true);
+
+ if (rejectY) {
+ vData.velocityBuffer.clear();
+ vData.velocity = 0;
+ }
+ if (rejectX) {
+ hData.velocityBuffer.clear();
+ hData.velocity = 0;
+ }
+
+ if (hMoved || vMoved) {
+ q->movementStarting();
+ q->viewportMoved();
+ }
+
+ if (!lastPos.isNull()) {
+ qreal elapsed = qreal(QDeclarativeItemPrivate::elapsed(lastPosTime)) / 1000.;
+ if (elapsed <= 0)
+ return;
+ QDeclarativeItemPrivate::restart(lastPosTime);
+ qreal dy = event->pos().y()-lastPos.y();
+ if (q->yflick() && !rejectY)
+ vData.addVelocitySample(dy/elapsed, maxVelocity);
+ qreal dx = event->pos().x()-lastPos.x();
+ if (q->xflick() && !rejectX)
+ hData.addVelocitySample(dx/elapsed, maxVelocity);
+ }
+
+ lastPos = event->pos();
+}
+
+void QDeclarativeFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QDeclarativeFlickable);
+ stealMouse = false;
+ q->setKeepMouseGrab(false);
+ pressed = false;
+ if (!lastPosTime.isValid())
+ return;
+
+ // if we drag then pause before release we should not cause a flick.
+ qint64 elapsed = QDeclarativeItemPrivate::elapsed(lastPosTime);
+
+ vData.updateVelocity();
+ hData.updateVelocity();
+ vTime = timeline.time();
+
+ qreal velocity = elapsed < 100 ? vData.velocity : 0;
+ if (vData.atBeginning || vData.atEnd)
+ velocity /= 2;
+ if (q->yflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) {
+ velocityTimeline.reset(vData.smoothVelocity);
+ vData.smoothVelocity.setValue(-velocity);
+ flickY(velocity);
+ } else {
+ fixupY();
+ }
+
+ velocity = elapsed < 100 ? hData.velocity : 0;
+ if (hData.atBeginning || hData.atEnd)
+ velocity /= 2;
+ if (q->xflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) {
+ velocityTimeline.reset(hData.smoothVelocity);
+ hData.smoothVelocity.setValue(-velocity);
+ flickX(velocity);
+ } else {
+ fixupX();
+ }
+
+ if (!timeline.isActive())
+ q->movementEnding();
+}
+
+void QDeclarativeFlickable::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarativeFlickable);
+ if (d->interactive) {
+ if (!d->pressed)
+ d->handleMousePressEvent(event);
+ event->accept();
+ } else {
+ QDeclarativeItem::mousePressEvent(event);
+ }
+}
+
+void QDeclarativeFlickable::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarativeFlickable);
+ if (d->interactive) {
+ d->handleMouseMoveEvent(event);
+ event->accept();
+ } else {
+ QDeclarativeItem::mouseMoveEvent(event);
+ }
+}
+
+void QDeclarativeFlickable::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarativeFlickable);
+ if (d->interactive) {
+ d->clearDelayedPress();
+ d->handleMouseReleaseEvent(event);
+ event->accept();
+ ungrabMouse();
+ } else {
+ QDeclarativeItem::mouseReleaseEvent(event);
+ }
+}
+
+void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event)
+{
+ Q_D(QDeclarativeFlickable);
+ if (!d->interactive) {
+ QDeclarativeItem::wheelEvent(event);
+ } else if (yflick() && event->orientation() == Qt::Vertical) {
+ bool valid = false;
+ if (event->delta() > 0 && contentY() > -minYExtent()) {
+ d->vData.velocity = qMax(event->delta()*2 - d->vData.smoothVelocity.value(), qreal(d->maxVelocity/4));
+ valid = true;
+ } else if (event->delta() < 0 && contentY() < -maxYExtent()) {
+ d->vData.velocity = qMin(event->delta()*2 - d->vData.smoothVelocity.value(), qreal(-d->maxVelocity/4));
+ valid = true;
+ }
+ if (valid) {
+ d->vData.flicking = false;
+ d->flickY(d->vData.velocity);
+ if (d->vData.flicking) {
+ d->vMoved = true;
+ movementStarting();
+ }
+ event->accept();
+ }
+ } else if (xflick() && event->orientation() == Qt::Horizontal) {
+ bool valid = false;
+ if (event->delta() > 0 && contentX() > -minXExtent()) {
+ d->hData.velocity = qMax(event->delta()*2 - d->hData.smoothVelocity.value(), qreal(d->maxVelocity/4));
+ valid = true;
+ } else if (event->delta() < 0 && contentX() < -maxXExtent()) {
+ d->hData.velocity = qMin(event->delta()*2 - d->hData.smoothVelocity.value(), qreal(-d->maxVelocity/4));
+ valid = true;
+ }
+ if (valid) {
+ d->hData.flicking = false;
+ d->flickX(d->hData.velocity);
+ if (d->hData.flicking) {
+ d->hMoved = true;
+ movementStarting();
+ }
+ event->accept();
+ }
+ } else {
+ QDeclarativeItem::wheelEvent(event);
+ }
+}
+
+bool QDeclarativeFlickablePrivate::isOutermostPressDelay() const
+{
+ Q_Q(const QDeclarativeFlickable);
+ QDeclarativeItem *item = q->parentItem();
+ while (item) {
+ QDeclarativeFlickable *flick = qobject_cast<QDeclarativeFlickable*>(item);
+ if (flick && flick->pressDelay() > 0 && flick->isInteractive())
+ return false;
+ item = item->parentItem();
+ }
+
+ return true;
+}
+
+void QDeclarativeFlickablePrivate::captureDelayedPress(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QDeclarativeFlickable);
+ if (!q->scene() || pressDelay <= 0)
+ return;
+ if (!isOutermostPressDelay())
+ return;
+ delayedPressTarget = q->scene()->mouseGrabberItem();
+ delayedPressEvent = new QGraphicsSceneMouseEvent(event->type());
+ delayedPressEvent->setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ delayedPressEvent->setButtonDownPos(button, event->buttonDownPos(button));
+ delayedPressEvent->setButtonDownScenePos(button, event->buttonDownScenePos(button));
+ delayedPressEvent->setButtonDownScreenPos(button, event->buttonDownScreenPos(button));
+ }
+ }
+ delayedPressEvent->setButtons(event->buttons());
+ delayedPressEvent->setButton(event->button());
+ delayedPressEvent->setPos(event->pos());
+ delayedPressEvent->setScenePos(event->scenePos());
+ delayedPressEvent->setScreenPos(event->screenPos());
+ delayedPressEvent->setLastPos(event->lastPos());
+ delayedPressEvent->setLastScenePos(event->lastScenePos());
+ delayedPressEvent->setLastScreenPos(event->lastScreenPos());
+ delayedPressEvent->setModifiers(event->modifiers());
+ delayedPressTimer.start(pressDelay, q);
+}
+
+void QDeclarativeFlickablePrivate::clearDelayedPress()
+{
+ if (delayedPressEvent) {
+ delayedPressTimer.stop();
+ delete delayedPressEvent;
+ delayedPressEvent = 0;
+ }
+}
+
+void QDeclarativeFlickablePrivate::setRoundedViewportX(qreal x)
+{
+ contentItem->setX(qRound(x));
+}
+
+void QDeclarativeFlickablePrivate::setRoundedViewportY(qreal y)
+{
+ contentItem->setY(qRound(y));
+}
+
+void QDeclarativeFlickable::timerEvent(QTimerEvent *event)
+{
+ Q_D(QDeclarativeFlickable);
+ if (event->timerId() == d->delayedPressTimer.timerId()) {
+ d->delayedPressTimer.stop();
+ if (d->delayedPressEvent) {
+ QDeclarativeItem *grabber = scene() ? qobject_cast<QDeclarativeItem*>(scene()->mouseGrabberItem()) : 0;
+ if (!grabber || grabber != this) {
+ // We replay the mouse press but the grabber we had might not be interessted by the event (e.g. overlay)
+ // so we reset the grabber
+ if (scene()->mouseGrabberItem() == d->delayedPressTarget)
+ d->delayedPressTarget->ungrabMouse();
+ //Use the event handler that will take care of finding the proper item to propagate the event
+ QApplication::postEvent(scene(), d->delayedPressEvent);
+ } else {
+ delete d->delayedPressEvent;
+ }
+ d->delayedPressEvent = 0;
+ }
+ }
+}
+
+qreal QDeclarativeFlickable::minYExtent() const
+{
+ return 0.0;
+}
+
+qreal QDeclarativeFlickable::minXExtent() const
+{
+ return 0.0;
+}
+
+/* returns -ve */
+qreal QDeclarativeFlickable::maxXExtent() const
+{
+ return width() - vWidth();
+}
+/* returns -ve */
+qreal QDeclarativeFlickable::maxYExtent() const
+{
+ return height() - vHeight();
+}
+
+void QDeclarativeFlickable::viewportMoved()
+{
+ Q_D(QDeclarativeFlickable);
+
+ qreal prevX = d->lastFlickablePosition.x();
+ qreal prevY = d->lastFlickablePosition.y();
+ if (d->pressed || d->calcVelocity) {
+ int elapsed = QDeclarativeItemPrivate::restart(d->velocityTime);
+ if (elapsed > 0) {
+ qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / elapsed;
+ if (qAbs(horizontalVelocity) > 0) {
+ d->velocityTimeline.reset(d->hData.smoothVelocity);
+ d->velocityTimeline.move(d->hData.smoothVelocity, horizontalVelocity, d->reportedVelocitySmoothing);
+ d->velocityTimeline.move(d->hData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+ }
+ qreal verticalVelocity = (prevY - d->vData.move.value()) * 1000 / elapsed;
+ if (qAbs(verticalVelocity) > 0) {
+ d->velocityTimeline.reset(d->vData.smoothVelocity);
+ d->velocityTimeline.move(d->vData.smoothVelocity, verticalVelocity, d->reportedVelocitySmoothing);
+ d->velocityTimeline.move(d->vData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+ }
+ }
+ } else {
+ if (d->timeline.time() > d->vTime) {
+ d->velocityTimeline.clear();
+ qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / (d->timeline.time() - d->vTime);
+ qreal verticalVelocity = (prevY - d->vData.move.value()) * 1000 / (d->timeline.time() - d->vTime);
+ d->hData.smoothVelocity.setValue(horizontalVelocity);
+ d->vData.smoothVelocity.setValue(verticalVelocity);
+ }
+ }
+
+ if (!d->vData.inOvershoot && !d->vData.fixingUp && d->vData.flicking
+ && (d->vData.move.value() > minYExtent() || d->vData.move.value() < maxYExtent())
+ && qAbs(d->vData.smoothVelocity.value()) > 100) {
+ // Increase deceleration if we've passed a bound
+ d->vData.inOvershoot = true;
+ qreal maxDistance = d->overShootDistance(height());
+ d->timeline.reset(d->vData.move);
+ d->timeline.accel(d->vData.move, -d->vData.smoothVelocity.value(), d->deceleration*QML_FLICK_OVERSHOOTFRICTION, maxDistance);
+ d->timeline.callback(QDeclarativeTimeLineCallback(&d->vData.move, d->fixupY_callback, d));
+ }
+ if (!d->hData.inOvershoot && !d->hData.fixingUp && d->hData.flicking
+ && (d->hData.move.value() > minXExtent() || d->hData.move.value() < maxXExtent())
+ && qAbs(d->hData.smoothVelocity.value()) > 100) {
+ // Increase deceleration if we've passed a bound
+ d->hData.inOvershoot = true;
+ qreal maxDistance = d->overShootDistance(width());
+ d->timeline.reset(d->hData.move);
+ d->timeline.accel(d->hData.move, -d->hData.smoothVelocity.value(), d->deceleration*QML_FLICK_OVERSHOOTFRICTION, maxDistance);
+ d->timeline.callback(QDeclarativeTimeLineCallback(&d->hData.move, d->fixupX_callback, d));
+ }
+
+ d->lastFlickablePosition = QPointF(d->hData.move.value(), d->vData.move.value());
+
+ d->vTime = d->timeline.time();
+ d->updateBeginningEnd();
+}
+
+void QDeclarativeFlickable::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QDeclarativeFlickable);
+ QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
+
+ bool changed = false;
+ if (newGeometry.width() != oldGeometry.width()) {
+ if (xflick())
+ changed = true;
+ if (d->hData.viewSize < 0) {
+ d->contentItem->setWidth(width());
+ emit contentWidthChanged();
+ }
+ // Make sure that we're entirely in view.
+ if (!d->pressed && !d->hData.moving && !d->vData.moving) {
+ d->fixupMode = QDeclarativeFlickablePrivate::Immediate;
+ d->fixupX();
+ }
+ }
+ if (newGeometry.height() != oldGeometry.height()) {
+ if (yflick())
+ changed = true;
+ if (d->vData.viewSize < 0) {
+ d->contentItem->setHeight(height());
+ emit contentHeightChanged();
+ }
+ // Make sure that we're entirely in view.
+ if (!d->pressed && !d->hData.moving && !d->vData.moving) {
+ d->fixupMode = QDeclarativeFlickablePrivate::Immediate;
+ d->fixupY();
+ }
+ }
+
+ if (changed)
+ d->updateBeginningEnd();
+}
+
+void QDeclarativeFlickable::cancelFlick()
+{
+ Q_D(QDeclarativeFlickable);
+ d->timeline.reset(d->hData.move);
+ d->timeline.reset(d->vData.move);
+ movementEnding();
+}
+
+void QDeclarativeFlickablePrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
+{
+ QGraphicsObject *i = qobject_cast<QGraphicsObject *>(o);
+ if (i) {
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(i);
+ if (static_cast<QDeclarativeItemPrivate*>(d)->componentComplete) {
+ i->setParentItem(static_cast<QDeclarativeFlickablePrivate*>(prop->data)->contentItem);
+ } else {
+ d->setParentItemHelper(static_cast<QDeclarativeFlickablePrivate*>(prop->data)->contentItem, 0, 0);
+ }
+ } else {
+ o->setParent(prop->object);
+ }
+}
+
+int QDeclarativeFlickablePrivate::data_count(QDeclarativeListProperty<QObject> *property)
+{
+ QDeclarativeItem *contentItem= static_cast<QDeclarativeFlickablePrivate*>(property->data)->contentItem;
+ return contentItem->childItems().count() + contentItem->children().count();
+}
+
+QObject *QDeclarativeFlickablePrivate::data_at(QDeclarativeListProperty<QObject> *property, int index)
+{
+ QDeclarativeItem *contentItem = static_cast<QDeclarativeFlickablePrivate*>(property->data)->contentItem;
+
+ int childItemCount = contentItem->childItems().count();
+
+ if (index < 0)
+ return 0;
+
+ if (index < childItemCount) {
+ return contentItem->childItems().at(index)->toGraphicsObject();
+ } else {
+ return contentItem->children().at(index - childItemCount);
+ }
+
+ return 0;
+}
+
+void QDeclarativeFlickablePrivate::data_clear(QDeclarativeListProperty<QObject> *property)
+{
+ QDeclarativeItem *contentItem = static_cast<QDeclarativeFlickablePrivate*>(property->data)->contentItem;
+
+ const QList<QGraphicsItem*> graphicsItems = contentItem->childItems();
+ for (int i = 0; i < graphicsItems.count(); i++)
+ contentItem->scene()->removeItem(graphicsItems[i]);
+
+ const QList<QObject*> objects = contentItem->children();
+ for (int i = 0; i < objects.count(); i++)
+ objects[i]->setParent(0);
+}
+
+QDeclarativeListProperty<QObject> QDeclarativeFlickable::flickableData()
+{
+ Q_D(QDeclarativeFlickable);
+ return QDeclarativeListProperty<QObject>(this, (void *)d, QDeclarativeFlickablePrivate::data_append,
+ QDeclarativeFlickablePrivate::data_count,
+ QDeclarativeFlickablePrivate::data_at,
+ QDeclarativeFlickablePrivate::data_clear);
+}
+
+QDeclarativeListProperty<QGraphicsObject> QDeclarativeFlickable::flickableChildren()
+{
+ Q_D(QDeclarativeFlickable);
+ return QGraphicsItemPrivate::get(d->contentItem)->childrenList();
+}
+
+/*!
+ \qmlproperty enumeration Flickable::boundsBehavior
+ This property holds whether the surface may be dragged
+ beyond the Fickable's boundaries, or overshoot the
+ Flickable's boundaries when flicked.
+
+ This enables the feeling that the edges of the view are soft,
+ rather than a hard physical boundary.
+
+ The \c boundsBehavior can be one of:
+
+ \list
+ \o Flickable.StopAtBounds - the contents can not be dragged beyond the boundary
+ of the flickable, and flicks will not overshoot.
+ \o Flickable.DragOverBounds - the contents can be dragged beyond the boundary
+ of the Flickable, but flicks will not overshoot.
+ \o Flickable.DragAndOvershootBounds (default) - the contents can be dragged
+ beyond the boundary of the Flickable, and can overshoot the
+ boundary when flicked.
+ \endlist
+*/
+QDeclarativeFlickable::BoundsBehavior QDeclarativeFlickable::boundsBehavior() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->boundsBehavior;
+}
+
+void QDeclarativeFlickable::setBoundsBehavior(BoundsBehavior b)
+{
+ Q_D(QDeclarativeFlickable);
+ if (b == d->boundsBehavior)
+ return;
+ d->boundsBehavior = b;
+ emit boundsBehaviorChanged();
+}
+
+/*!
+ \qmlproperty real Flickable::contentWidth
+ \qmlproperty real Flickable::contentHeight
+
+ The dimensions of the content (the surface controlled by Flickable).
+ This should typically be set to the combined size of the items placed in the
+ Flickable.
+
+ The following snippet shows how these properties are used to display
+ an image that is larger than the Flickable item itself:
+
+ \snippet doc/src/snippets/declarative/flickable.qml document
+
+ In some cases, the the content dimensions can be automatically set
+ using the \l {Item::childrenRect.width}{childrenRect.width}
+ and \l {Item::childrenRect.height}{childrenRect.height} properties.
+*/
+qreal QDeclarativeFlickable::contentWidth() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->hData.viewSize;
+}
+
+void QDeclarativeFlickable::setContentWidth(qreal w)
+{
+ Q_D(QDeclarativeFlickable);
+ if (d->hData.viewSize == w)
+ return;
+ d->hData.viewSize = w;
+ if (w < 0)
+ d->contentItem->setWidth(width());
+ else
+ d->contentItem->setWidth(w);
+ // Make sure that we're entirely in view.
+ if (!d->pressed && !d->hData.moving && !d->vData.moving) {
+ d->fixupMode = QDeclarativeFlickablePrivate::Immediate;
+ d->fixupX();
+ } else if (!d->pressed && d->hData.fixingUp) {
+ d->fixupMode = QDeclarativeFlickablePrivate::ExtentChanged;
+ d->fixupX();
+ }
+ emit contentWidthChanged();
+ d->updateBeginningEnd();
+}
+
+qreal QDeclarativeFlickable::contentHeight() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->vData.viewSize;
+}
+
+void QDeclarativeFlickable::setContentHeight(qreal h)
+{
+ Q_D(QDeclarativeFlickable);
+ if (d->vData.viewSize == h)
+ return;
+ d->vData.viewSize = h;
+ if (h < 0)
+ d->contentItem->setHeight(height());
+ else
+ d->contentItem->setHeight(h);
+ // Make sure that we're entirely in view.
+ if (!d->pressed && !d->hData.moving && !d->vData.moving) {
+ d->fixupMode = QDeclarativeFlickablePrivate::Immediate;
+ d->fixupY();
+ } else if (!d->pressed && d->vData.fixingUp) {
+ d->fixupMode = QDeclarativeFlickablePrivate::ExtentChanged;
+ d->fixupY();
+ }
+ emit contentHeightChanged();
+ d->updateBeginningEnd();
+}
+
+/*!
+ \qmlmethod Flickable::resizeContent(real width, real height, QPointF center)
+ \preliminary
+ \since QtQuick 1.1
+
+ Resizes the content to \a width x \a height about \a center.
+
+ This does not scale the contents of the Flickable - it only resizes the \l contentWidth
+ and \l contentHeight.
+
+ Resizing the content may result in the content being positioned outside
+ the bounds of the Flickable. Calling \l returnToBounds() will
+ move the content back within legal bounds.
+*/
+void QDeclarativeFlickable::resizeContent(qreal w, qreal h, QPointF center)
+{
+ Q_D(QDeclarativeFlickable);
+ if (w != d->hData.viewSize) {
+ qreal oldSize = d->hData.viewSize;
+ d->hData.viewSize = w;
+ d->contentItem->setWidth(w);
+ emit contentWidthChanged();
+ if (center.x() != 0) {
+ qreal pos = center.x() * w / oldSize;
+ setContentX(contentX() + pos - center.x());
+ }
+ }
+ if (h != d->vData.viewSize) {
+ qreal oldSize = d->vData.viewSize;
+ d->vData.viewSize = h;
+ d->contentItem->setHeight(h);
+ emit contentHeightChanged();
+ if (center.y() != 0) {
+ qreal pos = center.y() * h / oldSize;
+ setContentY(contentY() + pos - center.y());
+ }
+ }
+ d->updateBeginningEnd();
+}
+
+/*!
+ \qmlmethod Flickable::returnToBounds()
+ \preliminary
+ \since QtQuick 1.1
+
+ Ensures the content is within legal bounds.
+
+ This may be called to ensure that the content is within legal bounds
+ after manually positioning the content.
+*/
+void QDeclarativeFlickable::returnToBounds()
+{
+ Q_D(QDeclarativeFlickable);
+ d->fixupX();
+ d->fixupY();
+}
+
+qreal QDeclarativeFlickable::vWidth() const
+{
+ Q_D(const QDeclarativeFlickable);
+ if (d->hData.viewSize < 0)
+ return width();
+ else
+ return d->hData.viewSize;
+}
+
+qreal QDeclarativeFlickable::vHeight() const
+{
+ Q_D(const QDeclarativeFlickable);
+ if (d->vData.viewSize < 0)
+ return height();
+ else
+ return d->vData.viewSize;
+}
+
+bool QDeclarativeFlickable::xflick() const
+{
+ Q_D(const QDeclarativeFlickable);
+ if (d->flickableDirection == QDeclarativeFlickable::AutoFlickDirection)
+ return vWidth() != width();
+ return d->flickableDirection & QDeclarativeFlickable::HorizontalFlick;
+}
+
+bool QDeclarativeFlickable::yflick() const
+{
+ Q_D(const QDeclarativeFlickable);
+ if (d->flickableDirection == QDeclarativeFlickable::AutoFlickDirection)
+ return vHeight() != height();
+ return d->flickableDirection & QDeclarativeFlickable::VerticalFlick;
+}
+
+bool QDeclarativeFlickable::sceneEvent(QEvent *event)
+{
+ bool rv = QDeclarativeItem::sceneEvent(event);
+ if (event->type() == QEvent::UngrabMouse) {
+ Q_D(QDeclarativeFlickable);
+ if (d->pressed) {
+ // if our mouse grab has been removed (probably by another Flickable),
+ // fix our state
+ d->pressed = false;
+ d->stealMouse = false;
+ setKeepMouseGrab(false);
+ }
+ }
+ return rv;
+}
+
+bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarativeFlickable);
+ QGraphicsSceneMouseEvent mouseEvent(event->type());
+ QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect();
+
+ QGraphicsScene *s = scene();
+ QDeclarativeItem *grabber = s ? qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem()) : 0;
+ QGraphicsItem *grabberItem = s ? s->mouseGrabberItem() : 0;
+ bool disabledItem = grabberItem && !grabberItem->isEnabled();
+ bool stealThisEvent = d->stealMouse;
+ if ((stealThisEvent || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) {
+ mouseEvent.setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button)));
+ }
+ }
+ mouseEvent.setScenePos(event->scenePos());
+ mouseEvent.setLastScenePos(event->lastScenePos());
+ mouseEvent.setPos(mapFromScene(event->scenePos()));
+ mouseEvent.setLastPos(mapFromScene(event->lastScenePos()));
+
+ switch(mouseEvent.type()) {
+ case QEvent::GraphicsSceneMouseMove:
+ d->handleMouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMousePress:
+ if (d->pressed && !event->spontaneous()) // we are already pressed - this is a delayed replay
+ return false;
+
+ d->handleMousePressEvent(&mouseEvent);
+ d->captureDelayedPress(event);
+ stealThisEvent = d->stealMouse; // Update stealThisEvent in case changed by function call above
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ if (d->delayedPressEvent) {
+ // We replay the mouse press but the grabber we had might not be interessted by the event (e.g. overlay)
+ // so we reset the grabber
+ if (s->mouseGrabberItem() == d->delayedPressTarget)
+ d->delayedPressTarget->ungrabMouse();
+ //Use the event handler that will take care of finding the proper item to propagate the event
+ QApplication::sendEvent(scene(), d->delayedPressEvent);
+ d->clearDelayedPress();
+ // We send the release
+ scene()->sendEvent(s->mouseGrabberItem(), event);
+ // And the event has been consumed
+ d->stealMouse = false;
+ d->pressed = false;
+ return true;
+ }
+ d->handleMouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem());
+ if ((grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this) || disabledItem) {
+ d->clearDelayedPress();
+ grabMouse();
+ }
+
+ return stealThisEvent || d->delayedPressEvent || disabledItem;
+ } else if (d->lastPosTime.isValid()) {
+ d->lastPosTime.invalidate();
+ }
+ if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) {
+ d->clearDelayedPress();
+ d->stealMouse = false;
+ d->pressed = false;
+ }
+
+ return false;
+}
+
+bool QDeclarativeFlickable::sceneEventFilter(QGraphicsItem *i, QEvent *e)
+{
+ Q_D(QDeclarativeFlickable);
+ if (!isVisible() || !d->interactive)
+ return QDeclarativeItem::sceneEventFilter(i, e);
+ switch (e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ return sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e));
+ default:
+ break;
+ }
+
+ return QDeclarativeItem::sceneEventFilter(i, e);
+}
+
+/*!
+ \qmlproperty real Flickable::maximumFlickVelocity
+ This property holds the maximum velocity that the user can flick the view in pixels/second.
+
+ The default value is platform dependent.
+*/
+qreal QDeclarativeFlickable::maximumFlickVelocity() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->maxVelocity;
+}
+
+void QDeclarativeFlickable::setMaximumFlickVelocity(qreal v)
+{
+ Q_D(QDeclarativeFlickable);
+ if (v == d->maxVelocity)
+ return;
+ d->maxVelocity = v;
+ emit maximumFlickVelocityChanged();
+}
+
+/*!
+ \qmlproperty real Flickable::flickDeceleration
+ This property holds the rate at which a flick will decelerate.
+
+ The default value is platform dependent.
+*/
+qreal QDeclarativeFlickable::flickDeceleration() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->deceleration;
+}
+
+void QDeclarativeFlickable::setFlickDeceleration(qreal deceleration)
+{
+ Q_D(QDeclarativeFlickable);
+ if (deceleration == d->deceleration)
+ return;
+ d->deceleration = deceleration;
+ emit flickDecelerationChanged();
+}
+
+bool QDeclarativeFlickable::isFlicking() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->hData.flicking || d->vData.flicking;
+}
+
+/*!
+ \qmlproperty bool Flickable::flicking
+ \qmlproperty bool Flickable::flickingHorizontally
+ \qmlproperty bool Flickable::flickingVertically
+
+ These properties describe whether the view is currently moving horizontally,
+ vertically or in either direction, due to the user flicking the view.
+*/
+bool QDeclarativeFlickable::isFlickingHorizontally() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->hData.flicking;
+}
+
+bool QDeclarativeFlickable::isFlickingVertically() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->vData.flicking;
+}
+
+/*!
+ \qmlproperty int Flickable::pressDelay
+
+ This property holds the time to delay (ms) delivering a press to
+ children of the Flickable. This can be useful where reacting
+ to a press before a flicking action has undesirable effects.
+
+ If the flickable is dragged/flicked before the delay times out
+ the press event will not be delivered. If the button is released
+ within the timeout, both the press and release will be delivered.
+
+ Note that for nested Flickables with pressDelay set, the pressDelay of
+ inner Flickables is overridden by the outermost Flickable.
+*/
+int QDeclarativeFlickable::pressDelay() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->pressDelay;
+}
+
+void QDeclarativeFlickable::setPressDelay(int delay)
+{
+ Q_D(QDeclarativeFlickable);
+ if (d->pressDelay == delay)
+ return;
+ d->pressDelay = delay;
+ emit pressDelayChanged();
+}
+
+
+bool QDeclarativeFlickable::isMoving() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->hData.moving || d->vData.moving;
+}
+
+/*!
+ \qmlproperty bool Flickable::moving
+ \qmlproperty bool Flickable::movingHorizontally
+ \qmlproperty bool Flickable::movingVertically
+
+ These properties describe whether the view is currently moving horizontally,
+ vertically or in either direction, due to the user either dragging or
+ flicking the view.
+*/
+bool QDeclarativeFlickable::isMovingHorizontally() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->hData.moving;
+}
+
+bool QDeclarativeFlickable::isMovingVertically() const
+{
+ Q_D(const QDeclarativeFlickable);
+ return d->vData.moving;
+}
+
+void QDeclarativeFlickable::movementStarting()
+{
+ Q_D(QDeclarativeFlickable);
+ if (d->hMoved && !d->hData.moving) {
+ d->hData.moving = true;
+ emit movingChanged();
+ emit movingHorizontallyChanged();
+ if (!d->vData.moving)
+ emit movementStarted();
+ }
+ else if (d->vMoved && !d->vData.moving) {
+ d->vData.moving = true;
+ emit movingChanged();
+ emit movingVerticallyChanged();
+ if (!d->hData.moving)
+ emit movementStarted();
+ }
+}
+
+void QDeclarativeFlickable::movementEnding()
+{
+ Q_D(QDeclarativeFlickable);
+ movementXEnding();
+ movementYEnding();
+ d->hData.smoothVelocity.setValue(0);
+ d->vData.smoothVelocity.setValue(0);
+}
+
+void QDeclarativeFlickable::movementXEnding()
+{
+ Q_D(QDeclarativeFlickable);
+ if (d->hData.flicking) {
+ d->hData.flicking = false;
+ emit flickingChanged();
+ emit flickingHorizontallyChanged();
+ if (!d->vData.flicking)
+ emit flickEnded();
+ }
+ if (!d->pressed && !d->stealMouse) {
+ if (d->hData.moving) {
+ d->hData.moving = false;
+ d->hMoved = false;
+ emit movingChanged();
+ emit movingHorizontallyChanged();
+ if (!d->vData.moving)
+ emit movementEnded();
+ }
+ }
+ d->hData.fixingUp = false;
+}
+
+void QDeclarativeFlickable::movementYEnding()
+{
+ Q_D(QDeclarativeFlickable);
+ if (d->vData.flicking) {
+ d->vData.flicking = false;
+ emit flickingChanged();
+ emit flickingVerticallyChanged();
+ if (!d->hData.flicking)
+ emit flickEnded();
+ }
+ if (!d->pressed && !d->stealMouse) {
+ if (d->vData.moving) {
+ d->vData.moving = false;
+ d->vMoved = false;
+ emit movingChanged();
+ emit movingVerticallyChanged();
+ if (!d->hData.moving)
+ emit movementEnded();
+ }
+ }
+ d->vData.fixingUp = false;
+}
+
+void QDeclarativeFlickablePrivate::updateVelocity()
+{
+ Q_Q(QDeclarativeFlickable);
+ emit q->horizontalVelocityChanged();
+ emit q->verticalVelocityChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p.h
new file mode 100644
index 00000000..c04246c8
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeflickable_p.h
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFLICKABLE_H
+#define QDECLARATIVEFLICKABLE_H
+
+#include "qdeclarativeitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeFlickablePrivate;
+class QDeclarativeFlickableVisibleArea;
+class Q_AUTOTEST_EXPORT QDeclarativeFlickable : public QDeclarativeItem
+{
+ 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(QDeclarativeItem *contentItem READ contentItem CONSTANT)
+
+ 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(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(QDeclarativeFlickableVisibleArea *visibleArea READ visibleArea CONSTANT)
+
+ Q_PROPERTY(QDeclarativeListProperty<QObject> flickableData READ flickableData)
+ Q_PROPERTY(QDeclarativeListProperty<QGraphicsObject> flickableChildren READ flickableChildren)
+ Q_CLASSINFO("DefaultProperty", "flickableData")
+
+ Q_ENUMS(FlickableDirection)
+ Q_ENUMS(BoundsBehavior)
+
+public:
+ QDeclarativeFlickable(QDeclarativeItem *parent=0);
+ ~QDeclarativeFlickable();
+
+ QDeclarativeListProperty<QObject> flickableData();
+ QDeclarativeListProperty<QGraphicsObject> 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);
+
+ bool isMoving() const;
+ bool isMovingHorizontally() const;
+ bool isMovingVertically() const;
+ bool isFlicking() const;
+ bool isFlickingHorizontally() const;
+ bool isFlickingVertically() 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;
+
+ QDeclarativeItem *contentItem();
+
+ enum FlickableDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 };
+ FlickableDirection flickableDirection() const;
+ void setFlickableDirection(FlickableDirection);
+
+ Q_INVOKABLE Q_REVISION(1) void resizeContent(qreal w, qreal h, QPointF center);
+ Q_INVOKABLE Q_REVISION(1) void returnToBounds();
+
+Q_SIGNALS:
+ void contentWidthChanged();
+ void contentHeightChanged();
+ void contentXChanged();
+ void contentYChanged();
+ void movingChanged();
+ void movingHorizontallyChanged();
+ void movingVerticallyChanged();
+ void flickingChanged();
+ void flickingHorizontallyChanged();
+ void flickingVerticallyChanged();
+ 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();
+
+protected:
+ virtual bool sceneEventFilter(QGraphicsItem *, QEvent *);
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void wheelEvent(QGraphicsSceneWheelEvent *event);
+ void timerEvent(QTimerEvent *event);
+
+ QDeclarativeFlickableVisibleArea *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 viewportMoved();
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ bool sceneEvent(QEvent *event);
+ bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
+
+ bool xflick() const;
+ bool yflick() const;
+ void cancelFlick();
+
+protected:
+ QDeclarativeFlickable(QDeclarativeFlickablePrivate &dd, QDeclarativeItem *parent);
+
+private:
+ Q_DISABLE_COPY(QDeclarativeFlickable)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeFlickable)
+ friend class QDeclarativeFlickableVisibleArea;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeFlickable)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h
new file mode 100644
index 00000000..e70767b1
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFLICKABLE_P_H
+#define QDECLARATIVEFLICKABLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeflickable_p.h"
+
+#include "private/qdeclarativeitem_p.h"
+#include "private/qdeclarativeitemchangelistener_p.h"
+
+#include <qdeclarative.h>
+#include <qdeclarativetimeline_p_p.h>
+#include <qdeclarativeanimation_p_p.h>
+
+#include <qdatetime.h>
+#include "qplatformdefs.h"
+
+QT_BEGIN_NAMESPACE
+
+// Really slow flicks can be annoying.
+#ifndef QML_FLICK_MINVELOCITY
+#define QML_FLICK_MINVELOCITY 175
+#endif
+
+const qreal MinimumFlickVelocity = QML_FLICK_MINVELOCITY;
+
+class QDeclarativeFlickableVisibleArea;
+class QDeclarativeFlickablePrivate : public QDeclarativeItemPrivate, public QDeclarativeItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QDeclarativeFlickable)
+
+public:
+ QDeclarativeFlickablePrivate();
+ void init();
+
+ struct Velocity : public QDeclarativeTimeLineValue
+ {
+ Velocity(QDeclarativeFlickablePrivate *p)
+ : parent(p) {}
+ virtual void setValue(qreal v) {
+ if (v != value()) {
+ QDeclarativeTimeLineValue::setValue(v);
+ parent->updateVelocity();
+ }
+ }
+ QDeclarativeFlickablePrivate *parent;
+ };
+
+ struct AxisData {
+ AxisData(QDeclarativeFlickablePrivate *fp, void (QDeclarativeFlickablePrivate::*func)(qreal))
+ : move(fp, func), viewSize(-1), smoothVelocity(fp), atEnd(false), atBeginning(true)
+ , fixingUp(false), inOvershoot(false), moving(false), flicking(false)
+ {}
+
+ void reset() {
+ velocityBuffer.clear();
+ dragStartOffset = 0;
+ fixingUp = false;
+ inOvershoot = false;
+ }
+
+ void addVelocitySample(qreal v, qreal maxVelocity);
+ void updateVelocity();
+
+ QDeclarativeTimeLineValueProxy<QDeclarativeFlickablePrivate> move;
+ qreal viewSize;
+ qreal pressPos;
+ qreal dragStartOffset;
+ qreal dragMinBound;
+ qreal dragMaxBound;
+ qreal velocity;
+ qreal flickTarget;
+ QDeclarativeFlickablePrivate::Velocity smoothVelocity;
+ QPODVector<qreal,10> velocityBuffer;
+ bool atEnd : 1;
+ bool atBeginning : 1;
+ bool fixingUp : 1;
+ bool inOvershoot : 1;
+ bool moving : 1;
+ bool flicking : 1;
+ };
+
+ void flickX(qreal velocity);
+ void flickY(qreal velocity);
+ virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity);
+
+ void fixupX();
+ void fixupY();
+ virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
+
+ void updateBeginningEnd();
+
+ bool isOutermostPressDelay() const;
+ void captureDelayedPress(QGraphicsSceneMouseEvent *event);
+ void clearDelayedPress();
+
+ void setRoundedViewportX(qreal x);
+ void setRoundedViewportY(qreal y);
+
+ qreal overShootDistance(qreal size);
+
+ void itemGeometryChanged(QDeclarativeItem *, const QRectF &, const QRectF &);
+
+public:
+ QDeclarativeItem *contentItem;
+
+ AxisData hData;
+ AxisData vData;
+
+ QDeclarativeTimeLine timeline;
+ bool hMoved : 1;
+ bool vMoved : 1;
+ bool stealMouse : 1;
+ bool pressed : 1;
+ bool interactive : 1;
+ bool calcVelocity : 1;
+ QElapsedTimer lastPosTime;
+ QPointF lastPos;
+ QPointF pressPos;
+ QElapsedTimer pressTime;
+ qreal deceleration;
+ qreal maxVelocity;
+ QElapsedTimer velocityTime;
+ QPointF lastFlickablePosition;
+ qreal reportedVelocitySmoothing;
+ QGraphicsSceneMouseEvent *delayedPressEvent;
+ QGraphicsItem *delayedPressTarget;
+ QBasicTimer delayedPressTimer;
+ int pressDelay;
+ int fixupDuration;
+
+ enum FixupMode { Normal, Immediate, ExtentChanged };
+ FixupMode fixupMode;
+
+ static void fixupY_callback(void *);
+ static void fixupX_callback(void *);
+
+ void updateVelocity();
+ int vTime;
+ QDeclarativeTimeLine velocityTimeline;
+ QDeclarativeFlickableVisibleArea *visibleArea;
+ QDeclarativeFlickable::FlickableDirection flickableDirection;
+ QDeclarativeFlickable::BoundsBehavior boundsBehavior;
+
+ void handleMousePressEvent(QGraphicsSceneMouseEvent *);
+ void handleMouseMoveEvent(QGraphicsSceneMouseEvent *);
+ void handleMouseReleaseEvent(QGraphicsSceneMouseEvent *);
+
+ // flickableData 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> *);
+};
+
+class QDeclarativeFlickableVisibleArea : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal xPosition READ xPosition NOTIFY xPositionChanged)
+ Q_PROPERTY(qreal yPosition READ yPosition NOTIFY yPositionChanged)
+ Q_PROPERTY(qreal widthRatio READ widthRatio NOTIFY widthRatioChanged)
+ Q_PROPERTY(qreal heightRatio READ heightRatio NOTIFY heightRatioChanged)
+
+public:
+ QDeclarativeFlickableVisibleArea(QDeclarativeFlickable *parent=0);
+
+ qreal xPosition() const;
+ qreal widthRatio() const;
+ qreal yPosition() const;
+ qreal heightRatio() const;
+
+ void updateVisible();
+
+signals:
+ void xPositionChanged(qreal xPosition);
+ void yPositionChanged(qreal yPosition);
+ void widthRatioChanged(qreal widthRatio);
+ void heightRatioChanged(qreal heightRatio);
+
+private:
+ QDeclarativeFlickable *flickable;
+ qreal m_xPosition;
+ qreal m_widthRatio;
+ qreal m_yPosition;
+ qreal m_heightRatio;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeFlickableVisibleArea)
+
+#endif
diff --git a/src/declarative/graphicsitems/qdeclarativeflipable.cpp b/src/declarative/graphicsitems/qdeclarativeflipable.cpp
new file mode 100644
index 00000000..11569607
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeflipable.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativeflipable_p.h"
+
+#include "private/qdeclarativeitem_p.h"
+#include "private/qdeclarativeguard_p.h"
+
+#include <qdeclarativeinfo.h>
+
+#include <QtGui/qgraphicstransform.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeFlipablePrivate : public QDeclarativeItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarativeFlipable)
+public:
+ QDeclarativeFlipablePrivate() : current(QDeclarativeFlipable::Front), front(0), back(0) {}
+
+ void updateSceneTransformFromParent();
+ void setBackTransform();
+
+ QDeclarativeFlipable::Side current;
+ QDeclarativeGuard<QGraphicsObject> front;
+ QDeclarativeGuard<QGraphicsObject> back;
+
+ bool wantBackXFlipped;
+ bool wantBackYFlipped;
+};
+
+/*!
+ \qmlclass Flipable QDeclarativeFlipable
+ \since 4.7
+ \ingroup qml-basic-interaction-elements
+ \brief The Flipable item provides a surface that can be flipped.
+ \inherits Item
+
+ Flipable is an item that can be visibly "flipped" between its front and
+ back sides, like a card. It is used together with \l Rotation, \l State
+ and \l Transition elements to produce a flipping effect.
+
+ The \l front and \l back properties are used to hold the items that are
+ shown respectively on the front and back sides of the flipable item.
+
+ \section1 Example Usage
+
+ The following example shows a Flipable item that flips whenever it is
+ clicked, rotating about the y-axis.
+
+ This flipable item has a \c flipped boolean property that is toggled
+ whenever the MouseArea within the flipable is clicked. When
+ \c flipped is true, the item changes to the "back" state; in this
+ state, the \c angle of the \l Rotation item is changed to 180
+ degrees to produce the flipping effect. When \c flipped is false, the
+ item reverts to the default state, in which the \c angle value is 0.
+
+ \snippet doc/src/snippets/declarative/flipable/flipable.qml 0
+
+ \image flipable.gif
+
+ The \l Transition creates the animation that changes the angle over
+ four seconds. When the item changes between its "back" and
+ default states, the NumberAnimation animates the angle between
+ its old and new values.
+
+ See \l {QML States} for details on state changes and the default
+ state, and \l {QML Animation and Transitions} for more information on how
+ animations work within transitions.
+
+ \sa {declarative/ui-components/flipable}{Flipable example}
+*/
+
+QDeclarativeFlipable::QDeclarativeFlipable(QDeclarativeItem *parent)
+: QDeclarativeItem(*(new QDeclarativeFlipablePrivate), parent)
+{
+}
+
+QDeclarativeFlipable::~QDeclarativeFlipable()
+{
+}
+
+/*!
+ \qmlproperty Item Flipable::front
+ \qmlproperty Item Flipable::back
+
+ The front and back sides of the flipable.
+*/
+
+QGraphicsObject *QDeclarativeFlipable::front()
+{
+ Q_D(const QDeclarativeFlipable);
+ return d->front;
+}
+
+void QDeclarativeFlipable::setFront(QGraphicsObject *front)
+{
+ Q_D(QDeclarativeFlipable);
+ if (d->front) {
+ qmlInfo(this) << tr("front is a write-once property");
+ return;
+ }
+ d->front = front;
+ d->front->setParentItem(this);
+ if (Back == d->current)
+ d->front->setOpacity(0.);
+ emit frontChanged();
+}
+
+QGraphicsObject *QDeclarativeFlipable::back()
+{
+ Q_D(const QDeclarativeFlipable);
+ return d->back;
+}
+
+void QDeclarativeFlipable::setBack(QGraphicsObject *back)
+{
+ Q_D(QDeclarativeFlipable);
+ if (d->back) {
+ qmlInfo(this) << tr("back is a write-once property");
+ return;
+ }
+ d->back = back;
+ d->back->setParentItem(this);
+ if (Front == d->current)
+ d->back->setOpacity(0.);
+ connect(back, SIGNAL(widthChanged()),
+ this, SLOT(retransformBack()));
+ connect(back, SIGNAL(heightChanged()),
+ this, SLOT(retransformBack()));
+ emit backChanged();
+}
+
+void QDeclarativeFlipable::retransformBack()
+{
+ Q_D(QDeclarativeFlipable);
+ if (d->current == QDeclarativeFlipable::Back && d->back)
+ d->setBackTransform();
+}
+
+/*!
+ \qmlproperty enumeration Flipable::side
+
+ The side of the Flipable currently visible. Possible values are \c
+ Flipable.Front and \c Flipable.Back.
+*/
+QDeclarativeFlipable::Side QDeclarativeFlipable::side() const
+{
+ Q_D(const QDeclarativeFlipable);
+ if (d->dirtySceneTransform)
+ const_cast<QDeclarativeFlipablePrivate *>(d)->ensureSceneTransform();
+
+ return d->current;
+}
+
+// determination on the currently visible side of the flipable
+// has to be done on the complete scene transform to give
+// correct results.
+void QDeclarativeFlipablePrivate::updateSceneTransformFromParent()
+{
+ Q_Q(QDeclarativeFlipable);
+
+ QDeclarativeItemPrivate::updateSceneTransformFromParent();
+ QPointF p1(0, 0);
+ QPointF p2(1, 0);
+ QPointF p3(1, 1);
+
+ QPointF scenep1 = sceneTransform.map(p1);
+ QPointF scenep2 = sceneTransform.map(p2);
+ QPointF scenep3 = sceneTransform.map(p3);
+ p1 = q->mapToParent(p1);
+ p2 = q->mapToParent(p2);
+ p3 = q->mapToParent(p3);
+
+ qreal cross = (scenep1.x() - scenep2.x()) * (scenep3.y() - scenep2.y()) -
+ (scenep1.y() - scenep2.y()) * (scenep3.x() - scenep2.x());
+
+ wantBackYFlipped = p1.x() >= p2.x();
+ wantBackXFlipped = p2.y() >= p3.y();
+
+ QDeclarativeFlipable::Side newSide;
+ if (cross > 0) {
+ newSide = QDeclarativeFlipable::Back;
+ } else {
+ newSide = QDeclarativeFlipable::Front;
+ }
+
+ if (newSide != current) {
+ current = newSide;
+ if (current == QDeclarativeFlipable::Back && back)
+ setBackTransform();
+ if (front)
+ front->setOpacity((current==QDeclarativeFlipable::Front)?qreal(1.):qreal(0.));
+ if (back)
+ back->setOpacity((current==QDeclarativeFlipable::Back)?qreal(1.):qreal(0.));
+ emit q->sideChanged();
+ }
+}
+
+/* Depends on the width/height of the back item, and so needs reevaulating
+ if those change.
+*/
+void QDeclarativeFlipablePrivate::setBackTransform()
+{
+ QTransform mat;
+ QGraphicsItemPrivate *dBack = QGraphicsItemPrivate::get(back);
+ mat.translate(dBack->width()/2,dBack->height()/2);
+ if (dBack->width() && wantBackYFlipped)
+ mat.rotate(180, Qt::YAxis);
+ if (dBack->height() && wantBackXFlipped)
+ mat.rotate(180, Qt::XAxis);
+ mat.translate(-dBack->width()/2,-dBack->height()/2);
+ back->setTransform(mat);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativeflipable_p.h b/src/declarative/graphicsitems/qdeclarativeflipable_p.h
new file mode 100644
index 00000000..f74cf8fc
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativeflipable_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFLIPABLE_H
+#define QDECLARATIVEFLIPABLE_H
+
+#include "qdeclarativeitem.h"
+
+#include <QtCore/QObject>
+#include <QtGui/QTransform>
+#include <QtGui/qvector3d.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeFlipablePrivate;
+class Q_AUTOTEST_EXPORT QDeclarativeFlipable : public QDeclarativeItem
+{
+ Q_OBJECT
+
+ Q_ENUMS(Side)
+ Q_PROPERTY(QGraphicsObject *front READ front WRITE setFront NOTIFY frontChanged)
+ Q_PROPERTY(QGraphicsObject *back READ back WRITE setBack NOTIFY backChanged)
+ Q_PROPERTY(Side side READ side NOTIFY sideChanged)
+ //### flipAxis
+ //### flipRotation
+public:
+ QDeclarativeFlipable(QDeclarativeItem *parent=0);
+ ~QDeclarativeFlipable();
+
+ QGraphicsObject *front();
+ void setFront(QGraphicsObject *);
+
+ QGraphicsObject *back();
+ void setBack(QGraphicsObject *);
+
+ enum Side { Front, Back };
+ Side side() const;
+
+Q_SIGNALS:
+ void frontChanged();
+ void backChanged();
+ void sideChanged();
+
+private Q_SLOTS:
+ void retransformBack();
+
+private:
+ Q_DISABLE_COPY(QDeclarativeFlipable)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeFlipable)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeFlipable)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEFLIPABLE_H
diff --git a/src/declarative/graphicsitems/qdeclarativefocuspanel.cpp b/src/declarative/graphicsitems/qdeclarativefocuspanel.cpp
new file mode 100644
index 00000000..489ee901
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativefocuspanel.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativefocuspanel_p.h"
+
+#include "private/qdeclarativeitem_p.h"
+
+#include <QtGui/qgraphicsscene.h>
+#include <QEvent>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass FocusPanel QDeclarativeFocusPanel
+ \since 4.7
+ \ingroup qml-basic-interaction-elements
+
+ \brief The FocusPanel item explicitly creates a focus panel.
+ \inherits Item
+
+ Focus panels assist in keyboard focus handling when building QML
+ applications. All the details are covered in the
+ \l {qmlfocus}{keyboard focus documentation}.
+*/
+
+QDeclarativeFocusPanel::QDeclarativeFocusPanel(QDeclarativeItem *parent) :
+ QDeclarativeItem(parent)
+{
+ Q_D(QDeclarativeItem);
+ d->flags |= QGraphicsItem::ItemIsPanel;
+}
+
+QDeclarativeFocusPanel::~QDeclarativeFocusPanel()
+{
+}
+
+/*!
+ \qmlproperty bool FocusPanel::active
+
+ Sets whether the item is the active focus panel.
+*/
+
+bool QDeclarativeFocusPanel::sceneEvent(QEvent *event)
+{
+ if (event->type() == QEvent::WindowActivate ||
+ event->type() == QEvent::WindowDeactivate)
+ emit activeChanged();
+ return QDeclarativeItem::sceneEvent(event);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativefocuspanel_p.h b/src/declarative/graphicsitems/qdeclarativefocuspanel_p.h
new file mode 100644
index 00000000..b7d1e773
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativefocuspanel_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFOCUSPANEL_H
+#define QDECLARATIVEFOCUSPANEL_H
+
+#include "qdeclarativeitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_AUTOTEST_EXPORT QDeclarativeFocusPanel : public QDeclarativeItem
+{
+ Q_OBJECT
+ Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
+public:
+ QDeclarativeFocusPanel(QDeclarativeItem *parent=0);
+ virtual ~QDeclarativeFocusPanel();
+
+Q_SIGNALS:
+ void activeChanged();
+
+protected:
+ bool sceneEvent(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QDeclarativeFocusPanel)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeItem)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeFocusPanel)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEFOCUSPANEL_H
diff --git a/src/declarative/graphicsitems/qdeclarativefocusscope.cpp b/src/declarative/graphicsitems/qdeclarativefocusscope.cpp
new file mode 100644
index 00000000..d76a27f7
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativefocusscope.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativefocusscope_p.h"
+
+#include "private/qdeclarativeitem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass FocusScope QDeclarativeFocusScope
+ \since 4.7
+ \ingroup qml-basic-interaction-elements
+
+ \brief The FocusScope object explicitly creates a focus scope.
+ \inherits Item
+
+ Focus scopes assist in keyboard focus handling when building reusable QML
+ components. All the details are covered in the
+ \l {qmlfocus}{keyboard focus documentation}.
+
+ \sa {declarative/keyinteraction/focus}{Keyboard focus example}
+*/
+
+QDeclarativeFocusScope::QDeclarativeFocusScope(QDeclarativeItem *parent) :
+ QDeclarativeItem(parent)
+{
+ Q_D(QDeclarativeItem);
+ d->flags |= QGraphicsItem::ItemIsFocusScope;
+}
+
+QDeclarativeFocusScope::~QDeclarativeFocusScope()
+{
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativefocusscope_p.h b/src/declarative/graphicsitems/qdeclarativefocusscope_p.h
new file mode 100644
index 00000000..5ddcc2ed
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativefocusscope_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFOCUSSCOPE_H
+#define QDECLARATIVEFOCUSSCOPE_H
+
+#include "qdeclarativeitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+//### set component root as focusscope
+class Q_AUTOTEST_EXPORT QDeclarativeFocusScope : public QDeclarativeItem
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeItem)
+public:
+ QDeclarativeFocusScope(QDeclarativeItem *parent=0);
+ virtual ~QDeclarativeFocusScope();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeFocusScope)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEFOCUSSCOPE_H
diff --git a/src/declarative/graphicsitems/qdeclarativegraphicswidget.cpp b/src/declarative/graphicsitems/qdeclarativegraphicswidget.cpp
new file mode 100644
index 00000000..43f131df
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativegraphicswidget.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 "qdeclarativegraphicswidget_p.h"
+#include "private/qdeclarativeanchors_p.h"
+#include "private/qdeclarativeitem_p.h"
+#include "private/qdeclarativeanchors_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeGraphicsWidgetPrivate : public QObjectPrivate {
+ Q_DECLARE_PUBLIC(QDeclarativeGraphicsWidget)
+public :
+ QDeclarativeGraphicsWidgetPrivate() :
+ _anchors(0), _anchorLines(0)
+ {}
+ QDeclarativeItemPrivate::AnchorLines *anchorLines() const;
+ QDeclarativeAnchors *_anchors;
+ mutable QDeclarativeItemPrivate::AnchorLines *_anchorLines;
+};
+
+QDeclarativeGraphicsWidget::QDeclarativeGraphicsWidget(QObject *parent) :
+ QObject(*new QDeclarativeGraphicsWidgetPrivate, parent)
+{
+}
+QDeclarativeGraphicsWidget::~QDeclarativeGraphicsWidget()
+{
+ Q_D(QDeclarativeGraphicsWidget);
+ delete d->_anchorLines; d->_anchorLines = 0;
+ delete d->_anchors; d->_anchors = 0;
+}
+
+QDeclarativeAnchors *QDeclarativeGraphicsWidget::anchors()
+{
+ Q_D(QDeclarativeGraphicsWidget);
+ if (!d->_anchors)
+ d->_anchors = new QDeclarativeAnchors(static_cast<QGraphicsObject *>(parent()));
+ return d->_anchors;
+}
+
+QDeclarativeItemPrivate::AnchorLines *QDeclarativeGraphicsWidgetPrivate::anchorLines() const
+{
+ Q_Q(const QDeclarativeGraphicsWidget);
+ if (!_anchorLines)
+ _anchorLines = new QDeclarativeItemPrivate::AnchorLines(static_cast<QGraphicsObject *>(q->parent()));
+ return _anchorLines;
+}
+
+QDeclarativeAnchorLine QDeclarativeGraphicsWidget::left() const
+{
+ Q_D(const QDeclarativeGraphicsWidget);
+ return d->anchorLines()->left;
+}
+
+QDeclarativeAnchorLine QDeclarativeGraphicsWidget::right() const
+{
+ Q_D(const QDeclarativeGraphicsWidget);
+ return d->anchorLines()->right;
+}
+
+QDeclarativeAnchorLine QDeclarativeGraphicsWidget::horizontalCenter() const
+{
+ Q_D(const QDeclarativeGraphicsWidget);
+ return d->anchorLines()->hCenter;
+}
+
+QDeclarativeAnchorLine QDeclarativeGraphicsWidget::top() const
+{
+ Q_D(const QDeclarativeGraphicsWidget);
+ return d->anchorLines()->top;
+}
+
+QDeclarativeAnchorLine QDeclarativeGraphicsWidget::bottom() const
+{
+ Q_D(const QDeclarativeGraphicsWidget);
+ return d->anchorLines()->bottom;
+}
+
+QDeclarativeAnchorLine QDeclarativeGraphicsWidget::verticalCenter() const
+{
+ Q_D(const QDeclarativeGraphicsWidget);
+ return d->anchorLines()->vCenter;
+}
+
+QT_END_NAMESPACE
+
+#include <moc_qdeclarativegraphicswidget_p.cpp>
diff --git a/src/declarative/graphicsitems/qdeclarativegraphicswidget_p.h b/src/declarative/graphicsitems/qdeclarativegraphicswidget_p.h
new file mode 100644
index 00000000..93242aca
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativegraphicswidget_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEGRAPHICSWIDGET_P_H
+#define QDECLARATIVEGRAPHICSWIDGET_P_H
+
+#include <QObject>
+#include <QtDeclarative/qdeclarativecomponent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeAnchorLine;
+class QDeclarativeAnchors;
+class QGraphicsObject;
+class QDeclarativeGraphicsWidgetPrivate;
+
+// ### TODO can the extension object be the anchor directly? We save one allocation -> awesome.
+class QDeclarativeGraphicsWidget : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QDeclarativeAnchors * anchors READ anchors DESIGNABLE false CONSTANT FINAL)
+ Q_PROPERTY(QDeclarativeAnchorLine left READ left CONSTANT FINAL)
+ Q_PROPERTY(QDeclarativeAnchorLine right READ right CONSTANT FINAL)
+ Q_PROPERTY(QDeclarativeAnchorLine horizontalCenter READ horizontalCenter CONSTANT FINAL)
+ Q_PROPERTY(QDeclarativeAnchorLine top READ top CONSTANT FINAL)
+ Q_PROPERTY(QDeclarativeAnchorLine bottom READ bottom CONSTANT FINAL)
+ Q_PROPERTY(QDeclarativeAnchorLine verticalCenter READ verticalCenter CONSTANT FINAL)
+ // ### TODO : QGraphicsWidget don't have a baseline concept yet.
+ //Q_PROPERTY(QDeclarativeAnchorLine baseline READ baseline CONSTANT FINAL)
+public:
+ QDeclarativeGraphicsWidget(QObject *parent = 0);
+ ~QDeclarativeGraphicsWidget();
+ QDeclarativeAnchors *anchors();
+ QDeclarativeAnchorLine left() const;
+ QDeclarativeAnchorLine right() const;
+ QDeclarativeAnchorLine horizontalCenter() const;
+ QDeclarativeAnchorLine top() const;
+ QDeclarativeAnchorLine bottom() const;
+ QDeclarativeAnchorLine verticalCenter() const;
+ Q_DISABLE_COPY(QDeclarativeGraphicsWidget)
+ Q_DECLARE_PRIVATE(QDeclarativeGraphicsWidget)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEGRAPHICSWIDGET_P_H
diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp
new file mode 100644
index 00000000..1d9348c7
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp
@@ -0,0 +1,3172 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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/qdeclarativegridview_p.h"
+
+#include "private/qdeclarativevisualitemmodel_p.h"
+#include "private/qdeclarativeflickable_p_p.h"
+
+#include "private/qdeclarativesmoothedanimation_p_p.h"
+#include <qdeclarativeguard_p.h>
+
+#include <qlistmodelinterface_p.h>
+#include <QKeyEvent>
+
+#include <qmath.h>
+#include <math.h>
+#include "qplatformdefs.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QML_FLICK_SNAPONETHRESHOLD
+#define QML_FLICK_SNAPONETHRESHOLD 30
+#endif
+
+//----------------------------------------------------------------------------
+
+class FxGridItem
+{
+public:
+ FxGridItem(QDeclarativeItem *i, QDeclarativeGridView *v) : item(i), view(v) {
+ attached = static_cast<QDeclarativeGridViewAttached*>(qmlAttachedPropertiesObject<QDeclarativeGridView>(item));
+ if (attached)
+ attached->setView(view);
+ }
+ ~FxGridItem() {}
+
+ qreal rowPos() const {
+ qreal rowPos = 0;
+ if (view->flow() == QDeclarativeGridView::LeftToRight) {
+ rowPos = item->y();
+ } else {
+ if (view->effectiveLayoutDirection() == Qt::RightToLeft)
+ rowPos = -view->cellWidth()-item->x();
+ else
+ rowPos = item->x();
+ }
+ return rowPos;
+ }
+ qreal colPos() const {
+ qreal colPos = 0;
+ if (view->flow() == QDeclarativeGridView::LeftToRight) {
+ if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
+ int colSize = view->cellWidth();
+ int columns = view->width()/colSize;
+ colPos = colSize * (columns-1) - item->x();
+ } else {
+ colPos = item->x();
+ }
+ } else {
+ colPos = item->y();
+ }
+
+ return colPos;
+ }
+
+ qreal endRowPos() const {
+ if (view->flow() == QDeclarativeGridView::LeftToRight) {
+ return item->y() + view->cellHeight() - 1;
+ } else {
+ if (view->effectiveLayoutDirection() == Qt::RightToLeft)
+ return -item->x() - 1;
+ else
+ return item->x() + view->cellWidth() - 1;
+ }
+ }
+ void setPosition(qreal col, qreal row) {
+ if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
+ if (view->flow() == QDeclarativeGridView::LeftToRight) {
+ int columns = view->width()/view->cellWidth();
+ item->setPos(QPointF((view->cellWidth() * (columns-1) - col), row));
+ } else {
+ item->setPos(QPointF(-view->cellWidth()-row, col));
+ }
+ } else {
+ if (view->flow() == QDeclarativeGridView::LeftToRight)
+ item->setPos(QPointF(col, row));
+ else
+ item->setPos(QPointF(row, col));
+ }
+
+ }
+ bool contains(qreal x, qreal y) const {
+ return (x >= item->x() && x < item->x() + view->cellWidth() &&
+ y >= item->y() && y < item->y() + view->cellHeight());
+ }
+
+ QDeclarativeItem *item;
+ QDeclarativeGridView *view;
+ QDeclarativeGridViewAttached *attached;
+ int index;
+};
+
+//----------------------------------------------------------------------------
+
+class QDeclarativeGridViewPrivate : public QDeclarativeFlickablePrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarativeGridView)
+
+public:
+ QDeclarativeGridViewPrivate()
+ : currentItem(0), layoutDirection(Qt::LeftToRight), flow(QDeclarativeGridView::LeftToRight)
+ , visibleIndex(0) , currentIndex(-1)
+ , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1), itemCount(0)
+ , highlightRangeStart(0), highlightRangeEnd(0)
+ , highlightRangeStartValid(false), highlightRangeEndValid(false)
+ , highlightRange(QDeclarativeGridView::NoHighlightRange)
+ , highlightComponent(0), highlight(0), trackedItem(0)
+ , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
+ , highlightMoveDuration(150)
+ , footerComponent(0), footer(0), headerComponent(0), header(0)
+ , bufferMode(BufferBefore | BufferAfter), snapMode(QDeclarativeGridView::NoSnap)
+ , ownModel(false), wrap(false), autoHighlight(true)
+ , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false)
+ , deferredRelease(false), haveHighlightRange(false), currentIndexCleared(false) {}
+
+ void init();
+ void clear();
+ FxGridItem *createItem(int modelIndex);
+ void releaseItem(FxGridItem *item);
+ void refill(qreal from, qreal to, bool doBuffer=false);
+
+ void updateGrid();
+ void scheduleLayout();
+ void layout();
+ void updateUnrequestedIndexes();
+ void updateUnrequestedPositions();
+ void updateTrackedItem();
+ void createHighlight();
+ void updateHighlight();
+ void updateCurrent(int modelIndex);
+ void updateHeader();
+ void updateFooter();
+ void fixupPosition();
+
+ FxGridItem *visibleItem(int modelIndex) const {
+ if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
+ for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
+ FxGridItem *item = visibleItems.at(i);
+ if (item->index == modelIndex)
+ return item;
+ }
+ }
+ return 0;
+ }
+
+ bool isRightToLeftTopToBottom() const {
+ Q_Q(const QDeclarativeGridView);
+ return flow == QDeclarativeGridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft;
+ }
+
+ void regenerate() {
+ Q_Q(QDeclarativeGridView);
+ if (q->isComponentComplete()) {
+ clear();
+ updateGrid();
+ setPosition(0);
+ q->refill();
+ updateCurrent(currentIndex);
+ }
+ }
+
+ void mirrorChange() {
+ Q_Q(QDeclarativeGridView);
+ regenerate();
+ }
+
+ qreal position() const {
+ Q_Q(const QDeclarativeGridView);
+ return flow == QDeclarativeGridView::LeftToRight ? q->contentY() : q->contentX();
+ }
+ void setPosition(qreal pos) {
+ Q_Q(QDeclarativeGridView);
+ if (flow == QDeclarativeGridView::LeftToRight) {
+ q->QDeclarativeFlickable::setContentY(pos);
+ q->QDeclarativeFlickable::setContentX(0);
+ } else {
+ if (q->effectiveLayoutDirection() == Qt::LeftToRight)
+ q->QDeclarativeFlickable::setContentX(pos);
+ else
+ q->QDeclarativeFlickable::setContentX(-pos-size());
+ q->QDeclarativeFlickable::setContentY(0);
+ }
+ }
+ int size() const {
+ Q_Q(const QDeclarativeGridView);
+ return flow == QDeclarativeGridView::LeftToRight ? q->height() : q->width();
+ }
+ qreal originPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty())
+ pos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
+ return pos;
+ }
+
+ qreal lastPosition() const {
+ qreal pos = 0;
+ if (model && model->count())
+ pos = rowPosAt(model->count() - 1) + rowSize();
+ return pos;
+ }
+
+ qreal startPosition() const {
+ return isRightToLeftTopToBottom() ? -lastPosition()+1 : originPosition();
+ }
+
+ qreal endPosition() const {
+ return isRightToLeftTopToBottom() ? -originPosition()+1 : lastPosition();
+
+ }
+
+ bool isValid() const {
+ return model && model->count() && model->isValid();
+ }
+
+ int rowSize() const {
+ return flow == QDeclarativeGridView::LeftToRight ? cellHeight : cellWidth;
+ }
+ int colSize() const {
+ return flow == QDeclarativeGridView::LeftToRight ? cellWidth : cellHeight;
+ }
+
+ qreal colPosAt(int modelIndex) const {
+ if (FxGridItem *item = visibleItem(modelIndex))
+ return item->colPos();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = (visibleIndex - modelIndex) % columns;
+ int col = visibleItems.first()->colPos() / colSize();
+ col = (columns - count + col) % columns;
+ return col * colSize();
+ } else {
+ int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
+ return visibleItems.last()->colPos() - count * colSize();
+ }
+ } else {
+ return (modelIndex % columns) * colSize();
+ }
+ return 0;
+ }
+ qreal rowPosAt(int modelIndex) const {
+ if (FxGridItem *item = visibleItem(modelIndex))
+ return item->rowPos();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int firstCol = visibleItems.first()->colPos() / colSize();
+ int col = visibleIndex - modelIndex + (columns - firstCol - 1);
+ int rows = col / columns;
+ return visibleItems.first()->rowPos() - rows * rowSize();
+ } else {
+ int count = modelIndex - visibleItems.last()->index;
+ int col = visibleItems.last()->colPos() + count * colSize();
+ int rows = col / (columns * colSize());
+ return visibleItems.last()->rowPos() + rows * rowSize();
+ }
+ } else {
+ qreal pos = (modelIndex / columns) * rowSize();
+ if (header)
+ pos += headerSize();
+ return pos;
+ }
+ return 0;
+ }
+
+ FxGridItem *firstVisibleItem() const {
+ const qreal pos = isRightToLeftTopToBottom() ? -position()-size() : position();
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem *item = visibleItems.at(i);
+ if (item->index != -1 && item->endRowPos() > pos)
+ return item;
+ }
+ return visibleItems.count() ? visibleItems.first() : 0;
+ }
+
+ int lastVisibleIndex() const {
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem *item = visibleItems.at(i);
+ if (item->index != -1)
+ return item->index;
+ }
+ return -1;
+ }
+
+ // Map a model index to visibleItems list index.
+ // These may differ if removed items are still present in the visible list,
+ // e.g. doing a removal animation
+ int mapFromModel(int modelIndex) const {
+ if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
+ return -1;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem *listItem = visibleItems.at(i);
+ if (listItem->index == modelIndex)
+ return i + visibleIndex;
+ if (listItem->index > modelIndex)
+ return -1;
+ }
+ return -1; // Not in visibleList
+ }
+
+ qreal snapPosAt(qreal pos) const {
+ Q_Q(const QDeclarativeGridView);
+ qreal snapPos = 0;
+ if (!visibleItems.isEmpty()) {
+ qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
+ pos += highlightStart;
+ pos += rowSize()/2;
+ snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
+ snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
+ snapPos -= highlightStart;
+ qreal maxExtent;
+ qreal minExtent;
+ if (isRightToLeftTopToBottom()) {
+ maxExtent = q->minXExtent();
+ minExtent = q->maxXExtent();
+ } else {
+ maxExtent = flow == QDeclarativeGridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent();
+ minExtent = flow == QDeclarativeGridView::LeftToRight ? -q->minYExtent() : -q->minXExtent();
+ }
+ if (snapPos > maxExtent)
+ snapPos = maxExtent;
+ if (snapPos < minExtent)
+ snapPos = minExtent;
+ }
+ return snapPos;
+ }
+
+ FxGridItem *snapItemAt(qreal pos) {
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem *item = visibleItems[i];
+ if (item->index == -1)
+ continue;
+ qreal itemTop = item->rowPos();
+ if (itemTop+rowSize()/2 >= pos && itemTop - rowSize()/2 <= pos)
+ return item;
+ }
+ return 0;
+ }
+
+ int snapIndex() {
+ int index = currentIndex;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem *item = visibleItems[i];
+ if (item->index == -1)
+ continue;
+ qreal itemTop = item->rowPos();
+ if (itemTop >= highlight->rowPos()-rowSize()/2 && itemTop < highlight->rowPos()+rowSize()/2) {
+ index = item->index;
+ if (item->colPos() >= highlight->colPos()-colSize()/2 && item->colPos() < highlight->colPos()+colSize()/2)
+ return item->index;
+ }
+ }
+ return index;
+ }
+
+ qreal headerSize() const {
+ if (!header)
+ return 0.0;
+
+ return flow == QDeclarativeGridView::LeftToRight
+ ? header->item->height()
+ : header->item->width();
+ }
+
+
+ virtual void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
+ Q_Q(const QDeclarativeGridView);
+ QDeclarativeFlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
+ if (item == q) {
+ if (newGeometry.height() != oldGeometry.height()
+ || newGeometry.width() != oldGeometry.width()) {
+ if (q->isComponentComplete()) {
+ updateGrid();
+ scheduleLayout();
+ }
+ }
+ } else if ((header && header->item == item) || (footer && footer->item == item)) {
+ if (header)
+ updateHeader();
+ if (footer)
+ updateFooter();
+ }
+ }
+
+ void positionViewAtIndex(int index, int mode);
+ virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
+ virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity);
+
+ // for debugging only
+ void checkVisible() const {
+ int skip = 0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem *listItem = visibleItems.at(i);
+ if (listItem->index == -1) {
+ ++skip;
+ } else if (listItem->index != visibleIndex + i - skip) {
+ for (int j = 0; j < visibleItems.count(); j++)
+ qDebug() << " index" << j << "item index" << visibleItems.at(j)->index;
+ qFatal("index %d %d %d", visibleIndex, i, listItem->index);
+ }
+ }
+ }
+
+ QDeclarativeGuard<QDeclarativeVisualModel> model;
+ QVariant modelVariant;
+ QList<FxGridItem*> visibleItems;
+ QHash<QDeclarativeItem*,int> unrequestedItems;
+ FxGridItem *currentItem;
+ Qt::LayoutDirection layoutDirection;
+ QDeclarativeGridView::Flow flow;
+ int visibleIndex;
+ int currentIndex;
+ int cellWidth;
+ int cellHeight;
+ int columns;
+ int requestedIndex;
+ int itemCount;
+ qreal highlightRangeStart;
+ qreal highlightRangeEnd;
+ bool highlightRangeStartValid;
+ bool highlightRangeEndValid;
+ QDeclarativeGridView::HighlightRangeMode highlightRange;
+ QDeclarativeComponent *highlightComponent;
+ FxGridItem *highlight;
+ FxGridItem *trackedItem;
+ enum MovementReason { Other, SetIndex, Mouse };
+ MovementReason moveReason;
+ int buffer;
+ QSmoothedAnimation *highlightXAnimator;
+ QSmoothedAnimation *highlightYAnimator;
+ int highlightMoveDuration;
+ QDeclarativeComponent *footerComponent;
+ FxGridItem *footer;
+ QDeclarativeComponent *headerComponent;
+ FxGridItem *header;
+ enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
+ int bufferMode;
+ QDeclarativeGridView::SnapMode snapMode;
+
+ bool ownModel : 1;
+ bool wrap : 1;
+ bool autoHighlight : 1;
+ bool fixCurrentVisibility : 1;
+ bool lazyRelease : 1;
+ bool layoutScheduled : 1;
+ bool deferredRelease : 1;
+ bool haveHighlightRange : 1;
+ bool currentIndexCleared : 1;
+};
+
+void QDeclarativeGridViewPrivate::init()
+{
+ Q_Q(QDeclarativeGridView);
+ QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
+ q->setFlag(QGraphicsItem::ItemIsFocusScope);
+ q->setFlickableDirection(QDeclarativeFlickable::VerticalFlick);
+ addItemChangeListener(this, Geometry);
+}
+
+void QDeclarativeGridViewPrivate::clear()
+{
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ visibleIndex = 0;
+ releaseItem(currentItem);
+ currentItem = 0;
+ createHighlight();
+ trackedItem = 0;
+ itemCount = 0;
+}
+
+FxGridItem *QDeclarativeGridViewPrivate::createItem(int modelIndex)
+{
+ Q_Q(QDeclarativeGridView);
+ // create object
+ requestedIndex = modelIndex;
+ FxGridItem *listItem = 0;
+ if (QDeclarativeItem *item = model->item(modelIndex, false)) {
+ listItem = new FxGridItem(item, q);
+ listItem->index = modelIndex;
+ if (model->completePending()) {
+ // complete
+ listItem->item->setZValue(1);
+ listItem->item->setParentItem(q->contentItem());
+ model->completeItem();
+ } else {
+ listItem->item->setParentItem(q->contentItem());
+ }
+ unrequestedItems.remove(listItem->item);
+ }
+ requestedIndex = -1;
+ return listItem;
+}
+
+
+void QDeclarativeGridViewPrivate::releaseItem(FxGridItem *item)
+{
+ Q_Q(QDeclarativeGridView);
+ if (!item || !model)
+ return;
+ if (trackedItem == item) {
+ QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+ if (model->release(item->item) == 0) {
+ // item was not destroyed, and we no longer reference it.
+ unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+ }
+ delete item;
+}
+
+void QDeclarativeGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
+{
+ Q_Q(QDeclarativeGridView);
+ if (!isValid() || !q->isComponentComplete())
+ return;
+ itemCount = model->count();
+ qreal bufferFrom = from - buffer;
+ qreal bufferTo = to + buffer;
+ qreal fillFrom = from;
+ qreal fillTo = to;
+ if (doBuffer && (bufferMode & BufferAfter))
+ fillTo = bufferTo;
+ if (doBuffer && (bufferMode & BufferBefore))
+ fillFrom = bufferFrom;
+
+ bool changed = false;
+
+ int colPos = colPosAt(visibleIndex);
+ int rowPos = rowPosAt(visibleIndex);
+ int modelIndex = visibleIndex;
+ if (visibleItems.count()) {
+ rowPos = visibleItems.last()->rowPos();
+ colPos = visibleItems.last()->colPos() + colSize();
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ rowPos += rowSize();
+ }
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
+ --i;
+ modelIndex = visibleItems.at(i)->index + 1;
+ }
+
+ if (visibleItems.count() && (fillFrom > rowPos + rowSize()*2
+ || fillTo < rowPosAt(visibleIndex) - rowSize())) {
+ // We've jumped more than a page. Estimate which items are now
+ // visible and fill from there.
+ int count = (fillFrom - (rowPos + rowSize())) / (rowSize()) * columns;
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ modelIndex += count;
+ if (modelIndex >= model->count())
+ modelIndex = model->count() - 1;
+ else if (modelIndex < 0)
+ modelIndex = 0;
+ modelIndex = modelIndex / columns * columns;
+ visibleIndex = modelIndex;
+ colPos = colPosAt(visibleIndex);
+ rowPos = rowPosAt(visibleIndex);
+ }
+
+ int colNum = colPos / colSize();
+
+ FxGridItem *item = 0;
+
+ // Item creation and release is staggered in order to avoid
+ // creating/releasing multiple items in one frame
+ // while flicking (as much as possible).
+ while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) {
+// qDebug() << "refill: append item" << modelIndex;
+ if (!(item = createItem(modelIndex)))
+ break;
+ item->setPosition(colPos, rowPos);
+ visibleItems.append(item);
+ colPos += colSize();
+ colNum++;
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ colNum = 0;
+ rowPos += rowSize();
+ }
+ ++modelIndex;
+ changed = true;
+ if (doBuffer) // never buffer more than one item per frame
+ break;
+ }
+
+ if (visibleItems.count()) {
+ rowPos = visibleItems.first()->rowPos();
+ colPos = visibleItems.first()->colPos() - colSize();
+ if (colPos < 0) {
+ colPos = colSize() * (columns - 1);
+ rowPos -= rowSize();
+ }
+ }
+ colNum = colPos / colSize();
+ while (visibleIndex > 0 && rowPos + rowSize() - 1 >= fillFrom - rowSize()*(colNum+1)/(columns+1)){
+// qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
+ if (!(item = createItem(visibleIndex-1)))
+ break;
+ --visibleIndex;
+ item->setPosition(colPos, rowPos);
+ visibleItems.prepend(item);
+ colPos -= colSize();
+ colNum--;
+ if (colPos < 0) {
+ colPos = colSize() * (columns - 1);
+ colNum = columns-1;
+ rowPos -= rowSize();
+ }
+ changed = true;
+ if (doBuffer) // never buffer more than one item per frame
+ break;
+ }
+
+ if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
+ while (visibleItems.count() > 1
+ && (item = visibleItems.first())
+ && item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
+ if (item->attached->delayRemove())
+ break;
+// qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
+ if (item->index != -1)
+ visibleIndex++;
+ visibleItems.removeFirst();
+ releaseItem(item);
+ changed = true;
+ }
+ while (visibleItems.count() > 1
+ && (item = visibleItems.last())
+ && item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
+ if (item->attached->delayRemove())
+ break;
+// qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+ visibleItems.removeLast();
+ releaseItem(item);
+ changed = true;
+ }
+ deferredRelease = false;
+ } else {
+ deferredRelease = true;
+ }
+ if (changed) {
+ if (header)
+ updateHeader();
+ if (footer)
+ updateFooter();
+ if (flow == QDeclarativeGridView::LeftToRight)
+ q->setContentHeight(endPosition() - startPosition());
+ else
+ q->setContentWidth(endPosition() - startPosition());
+ } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
+ refill(from, to, true);
+ }
+ lazyRelease = false;
+}
+
+void QDeclarativeGridViewPrivate::updateGrid()
+{
+ Q_Q(QDeclarativeGridView);
+
+ columns = (int)qMax((flow == QDeclarativeGridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.));
+ if (isValid()) {
+ if (flow == QDeclarativeGridView::LeftToRight)
+ q->setContentHeight(endPosition() - startPosition());
+ else
+ q->setContentWidth(lastPosition() - originPosition());
+ }
+}
+
+void QDeclarativeGridViewPrivate::scheduleLayout()
+{
+ Q_Q(QDeclarativeGridView);
+ if (!layoutScheduled) {
+ layoutScheduled = true;
+ QCoreApplication::postEvent(q, new QEvent(QEvent::User), Qt::HighEventPriority);
+ }
+}
+
+void QDeclarativeGridViewPrivate::layout()
+{
+ Q_Q(QDeclarativeGridView);
+ layoutScheduled = false;
+ if (!isValid() && !visibleItems.count()) {
+ clear();
+ return;
+ }
+ if (visibleItems.count()) {
+ qreal rowPos = visibleItems.first()->rowPos();
+ qreal colPos = visibleItems.first()->colPos();
+ int col = visibleIndex % columns;
+ if (colPos != col * colSize()) {
+ colPos = col * colSize();
+ visibleItems.first()->setPosition(colPos, rowPos);
+ }
+ for (int i = 1; i < visibleItems.count(); ++i) {
+ FxGridItem *item = visibleItems.at(i);
+ colPos += colSize();
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ rowPos += rowSize();
+ }
+ item->setPosition(colPos, rowPos);
+ }
+ }
+ if (header)
+ updateHeader();
+ if (footer)
+ updateFooter();
+ q->refill();
+ updateHighlight();
+ moveReason = Other;
+ if (flow == QDeclarativeGridView::LeftToRight) {
+ q->setContentHeight(endPosition() - startPosition());
+ fixupY();
+ } else {
+ q->setContentWidth(endPosition() - startPosition());
+ fixupX();
+ }
+ updateUnrequestedPositions();
+}
+
+void QDeclarativeGridViewPrivate::updateUnrequestedIndexes()
+{
+ Q_Q(QDeclarativeGridView);
+ QHash<QDeclarativeItem*,int>::iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+ *it = model->indexOf(it.key(), q);
+}
+
+void QDeclarativeGridViewPrivate::updateUnrequestedPositions()
+{
+ QHash<QDeclarativeItem*,int>::const_iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
+ QDeclarativeItem *item = it.key();
+ if (flow == QDeclarativeGridView::LeftToRight) {
+ item->setPos(QPointF(colPosAt(*it), rowPosAt(*it)));
+ } else {
+ if (isRightToLeftTopToBottom())
+ item->setPos(QPointF(-rowPosAt(*it)-item->width(), colPosAt(*it)));
+ else
+ item->setPos(QPointF(rowPosAt(*it), colPosAt(*it)));
+ }
+ }
+}
+
+void QDeclarativeGridViewPrivate::updateTrackedItem()
+{
+ Q_Q(QDeclarativeGridView);
+ FxGridItem *item = currentItem;
+ if (highlight)
+ item = highlight;
+
+ if (trackedItem && item != trackedItem) {
+ QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+
+ if (!trackedItem && item) {
+ trackedItem = item;
+ QObject::connect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::connect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
+ }
+ if (trackedItem)
+ q->trackedPositionChanged();
+}
+
+void QDeclarativeGridViewPrivate::createHighlight()
+{
+ Q_Q(QDeclarativeGridView);
+ bool changed = false;
+ if (highlight) {
+ if (trackedItem == highlight)
+ trackedItem = 0;
+ if (highlight->item->scene())
+ highlight->item->scene()->removeItem(highlight->item);
+ highlight->item->deleteLater();
+ delete highlight;
+ highlight = 0;
+ delete highlightXAnimator;
+ delete highlightYAnimator;
+ highlightXAnimator = 0;
+ highlightYAnimator = 0;
+ changed = true;
+ }
+
+ if (currentItem) {
+ QDeclarativeItem *item = 0;
+ if (highlightComponent) {
+ QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
+ QObject *nobj = highlightComponent->create(highlightContext);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(highlightContext, nobj);
+ item = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete highlightContext;
+ }
+ } else {
+ item = new QDeclarativeItem;
+ QDeclarative_setParent_noEvent(item, q->contentItem());
+ item->setParentItem(q->contentItem());
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q->contentItem());
+ item->setParentItem(q->contentItem());
+ highlight = new FxGridItem(item, q);
+ if (currentItem && autoHighlight)
+ highlight->setPosition(currentItem->colPos(), currentItem->rowPos());
+ highlightXAnimator = new QSmoothedAnimation(q);
+ highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x"));
+ highlightXAnimator->userDuration = highlightMoveDuration;
+ highlightYAnimator = new QSmoothedAnimation(q);
+ highlightYAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("y"));
+ highlightYAnimator->userDuration = highlightMoveDuration;
+ if (autoHighlight) {
+ highlightXAnimator->restart();
+ highlightYAnimator->restart();
+ }
+ changed = true;
+ }
+ }
+ if (changed)
+ emit q->highlightItemChanged();
+}
+
+void QDeclarativeGridViewPrivate::updateHighlight()
+{
+ if ((!currentItem && highlight) || (currentItem && !highlight))
+ createHighlight();
+ if (currentItem && autoHighlight && highlight && !hData.moving && !vData.moving) {
+ // auto-update highlight
+ highlightXAnimator->to = currentItem->item->x();
+ highlightYAnimator->to = currentItem->item->y();
+ highlight->item->setWidth(currentItem->item->width());
+ highlight->item->setHeight(currentItem->item->height());
+ highlightXAnimator->restart();
+ highlightYAnimator->restart();
+ }
+ updateTrackedItem();
+}
+
+void QDeclarativeGridViewPrivate::updateCurrent(int modelIndex)
+{
+ Q_Q(QDeclarativeGridView);
+ if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
+ if (currentItem) {
+ currentItem->attached->setIsCurrentItem(false);
+ releaseItem(currentItem);
+ currentItem = 0;
+ currentIndex = modelIndex;
+ emit q->currentIndexChanged();
+ updateHighlight();
+ } else if (currentIndex != modelIndex) {
+ currentIndex = modelIndex;
+ emit q->currentIndexChanged();
+ }
+ return;
+ }
+
+ if (currentItem && currentIndex == modelIndex) {
+ updateHighlight();
+ return;
+ }
+
+ FxGridItem *oldCurrentItem = currentItem;
+ currentIndex = modelIndex;
+ currentItem = createItem(modelIndex);
+ fixCurrentVisibility = true;
+ if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
+ oldCurrentItem->attached->setIsCurrentItem(false);
+ if (currentItem) {
+ currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex));
+ currentItem->item->setFocus(true);
+ currentItem->attached->setIsCurrentItem(true);
+ }
+ updateHighlight();
+ emit q->currentIndexChanged();
+ releaseItem(oldCurrentItem);
+}
+
+void QDeclarativeGridViewPrivate::updateFooter()
+{
+ Q_Q(QDeclarativeGridView);
+ if (!footer && footerComponent) {
+ QDeclarativeItem *item = 0;
+ QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
+ QObject *nobj = footerComponent->create(context);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(context, nobj);
+ item = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete context;
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q->contentItem());
+ item->setParentItem(q->contentItem());
+ item->setZValue(1);
+ QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
+ itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ footer = new FxGridItem(item, q);
+ }
+ }
+ if (footer) {
+ qreal colOffset = 0;
+ qreal rowOffset;
+ if (isRightToLeftTopToBottom()) {
+ rowOffset = footer->item->width()-cellWidth;
+ } else {
+ rowOffset = 0;
+ if (q->effectiveLayoutDirection() == Qt::RightToLeft)
+ colOffset = footer->item->width()-cellWidth;
+ }
+ if (visibleItems.count()) {
+ qreal endPos = lastPosition();
+ if (lastVisibleIndex() == model->count()-1) {
+ footer->setPosition(colOffset, endPos + rowOffset);
+ } else {
+ qreal visiblePos = isRightToLeftTopToBottom() ? -position() : position() + size();
+ if (endPos <= visiblePos || footer->endRowPos() < endPos + rowOffset)
+ footer->setPosition(colOffset, endPos + rowOffset);
+ }
+ } else {
+ qreal endPos = 0;
+ if (header) {
+ endPos += flow == QDeclarativeGridView::LeftToRight ? header->item->height() : header->item->width();
+ }
+ footer->setPosition(colOffset, endPos);
+ }
+ }
+}
+
+void QDeclarativeGridViewPrivate::updateHeader()
+{
+ Q_Q(QDeclarativeGridView);
+ if (!header && headerComponent) {
+ QDeclarativeItem *item = 0;
+ QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
+ QObject *nobj = headerComponent->create(context);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(context, nobj);
+ item = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete context;
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q->contentItem());
+ item->setParentItem(q->contentItem());
+ item->setZValue(1);
+ QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
+ itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ header = new FxGridItem(item, q);
+ }
+ }
+ if (header) {
+ qreal colOffset = 0;
+ qreal rowOffset;
+ if (isRightToLeftTopToBottom()) {
+ rowOffset = -cellWidth;
+ } else {
+ rowOffset = -headerSize();
+ if (q->effectiveLayoutDirection() == Qt::RightToLeft)
+ colOffset = header->item->width()-cellWidth;
+ }
+ if (visibleItems.count()) {
+ qreal startPos = originPosition();
+ if (visibleIndex == 0) {
+ header->setPosition(colOffset, startPos + rowOffset);
+ } else {
+ qreal tempPos = isRightToLeftTopToBottom() ? -position()-size() : position();
+ qreal headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos();
+ if (tempPos <= startPos || headerPos > startPos + rowOffset)
+ header->setPosition(colOffset, startPos + rowOffset);
+ }
+ } else {
+ header->setPosition(colOffset, 0);
+ }
+ }
+}
+
+void QDeclarativeGridViewPrivate::fixupPosition()
+{
+ moveReason = Other;
+ if (flow == QDeclarativeGridView::LeftToRight)
+ fixupY();
+ else
+ fixupX();
+}
+
+void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
+{
+ if ((flow == QDeclarativeGridView::TopToBottom && &data == &vData)
+ || (flow == QDeclarativeGridView::LeftToRight && &data == &hData))
+ return;
+
+ fixupMode = moveReason == Mouse ? fixupMode : Immediate;
+
+ qreal highlightStart;
+ qreal highlightEnd;
+ qreal viewPos;
+ if (isRightToLeftTopToBottom()) {
+ // Handle Right-To-Left exceptions
+ viewPos = -position()-size();
+ highlightStart = highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
+ highlightEnd = highlightRangeEndValid ? size()-highlightRangeStart : highlightRangeEnd;
+ } else {
+ viewPos = position();
+ highlightStart = highlightRangeStart;
+ highlightEnd = highlightRangeEnd;
+ }
+
+ bool strictHighlightRange = haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange;
+
+ if (snapMode != QDeclarativeGridView::NoSnap) {
+ qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position();
+ if (snapMode == QDeclarativeGridView::SnapOneRow && moveReason == Mouse) {
+ // if we've been dragged < rowSize()/2 then bias towards the next row
+ qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal bias = 0;
+ if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < rowSize()/2)
+ bias = rowSize()/2;
+ else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -rowSize()/2)
+ bias = -rowSize()/2;
+ if (isRightToLeftTopToBottom())
+ bias = -bias;
+ tempPosition -= bias;
+ }
+ FxGridItem *topItem = snapItemAt(tempPosition+highlightStart);
+ if (!topItem && strictHighlightRange && currentItem) {
+ // StrictlyEnforceRange always keeps an item in range
+ updateHighlight();
+ topItem = currentItem;
+ }
+ FxGridItem *bottomItem = snapItemAt(tempPosition+highlightEnd);
+ if (!bottomItem && strictHighlightRange && currentItem) {
+ // StrictlyEnforceRange always keeps an item in range
+ updateHighlight();
+ bottomItem = currentItem;
+ }
+ qreal pos;
+ bool isInBounds = -position() > maxExtent && -position() <= minExtent;
+ if (topItem && (isInBounds || strictHighlightRange)) {
+ if (topItem->index == 0 && header && tempPosition+highlightStart < header->rowPos()+headerSize()/2 && !strictHighlightRange) {
+ pos = isRightToLeftTopToBottom() ? - header->rowPos() + highlightStart - size() : header->rowPos() - highlightStart;
+ } else {
+ if (isRightToLeftTopToBottom())
+ pos = qMax(qMin(-topItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
+ else
+ pos = qMax(qMin(topItem->rowPos() - highlightStart, -maxExtent), -minExtent);
+ }
+ } else if (bottomItem && isInBounds) {
+ if (isRightToLeftTopToBottom())
+ pos = qMax(qMin(-bottomItem->rowPos() + highlightEnd - size(), -maxExtent), -minExtent);
+ else
+ pos = qMax(qMin(bottomItem->rowPos() - highlightEnd, -maxExtent), -minExtent);
+ } else {
+ QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent);
+ return;
+ }
+ qreal dist = qAbs(data.move + pos);
+ if (dist > 0) {
+ timeline.reset(data.move);
+ if (fixupMode != Immediate) {
+ timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
+ data.fixingUp = true;
+ } else {
+ timeline.set(data.move, -pos);
+ }
+ vTime = timeline.time();
+ }
+ } else if (haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) {
+ if (currentItem) {
+ updateHighlight();
+ qreal pos = currentItem->rowPos();
+ if (viewPos < pos + rowSize() - highlightEnd)
+ viewPos = pos + rowSize() - highlightEnd;
+ if (viewPos > pos - highlightStart)
+ viewPos = pos - highlightStart;
+ if (isRightToLeftTopToBottom())
+ viewPos = -viewPos-size();
+ timeline.reset(data.move);
+ if (viewPos != position()) {
+ if (fixupMode != Immediate) {
+ timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
+ data.fixingUp = true;
+ } else {
+ timeline.set(data.move, -viewPos);
+ }
+ }
+ vTime = timeline.time();
+ }
+ } else {
+ QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent);
+ }
+ data.inOvershoot = false;
+ fixupMode = Normal;
+}
+
+void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity)
+{
+ Q_Q(QDeclarativeGridView);
+ data.fixingUp = false;
+ moveReason = Mouse;
+ if ((!haveHighlightRange || highlightRange != QDeclarativeGridView::StrictlyEnforceRange)
+ && snapMode == QDeclarativeGridView::NoSnap) {
+ QDeclarativeFlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
+ return;
+ }
+ qreal maxDistance = 0;
+ qreal dataValue = isRightToLeftTopToBottom() ? -data.move.value()+size() : data.move.value();
+ // -ve velocity means list is moving up/left
+ if (velocity > 0) {
+ if (data.move.value() < minExtent) {
+ if (snapMode == QDeclarativeGridView::SnapOneRow) {
+ // if we've been dragged < averageSize/2 then bias towards the next item
+ qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal bias = dist < rowSize()/2 ? rowSize()/2 : 0;
+ if (isRightToLeftTopToBottom())
+ bias = -bias;
+ data.flickTarget = -snapPosAt(-dataValue - bias);
+ maxDistance = qAbs(data.flickTarget - data.move.value());
+ velocity = maxVelocity;
+ } else {
+ maxDistance = qAbs(minExtent - data.move.value());
+ }
+ }
+ if (snapMode == QDeclarativeGridView::NoSnap && highlightRange != QDeclarativeGridView::StrictlyEnforceRange)
+ data.flickTarget = minExtent;
+ } else {
+ if (data.move.value() > maxExtent) {
+ if (snapMode == QDeclarativeGridView::SnapOneRow) {
+ // if we've been dragged < averageSize/2 then bias towards the next item
+ qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
+ qreal bias = -dist < rowSize()/2 ? rowSize()/2 : 0;
+ if (isRightToLeftTopToBottom())
+ bias = -bias;
+ data.flickTarget = -snapPosAt(-dataValue + bias);
+ maxDistance = qAbs(data.flickTarget - data.move.value());
+ velocity = -maxVelocity;
+ } else {
+ maxDistance = qAbs(maxExtent - data.move.value());
+ }
+ }
+ if (snapMode == QDeclarativeGridView::NoSnap && highlightRange != QDeclarativeGridView::StrictlyEnforceRange)
+ data.flickTarget = maxExtent;
+ }
+
+ bool overShoot = boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds;
+
+ if (maxDistance > 0 || overShoot) {
+ // This mode requires the grid to stop exactly on a row boundary.
+ qreal v = velocity;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ qreal accel = deceleration;
+ qreal v2 = v * v;
+ qreal overshootDist = qreal(0.0);
+ if ((maxDistance > qreal(0.0) && v2 / (2.0f * maxDistance) < accel) || snapMode == QDeclarativeGridView::SnapOneRow) {
+ // + rowSize()/4 to encourage moving at least one item in the flick direction
+ qreal dist = v2 / (accel * qreal(2.0)) + rowSize()/4;
+ dist = qMin(dist, maxDistance);
+ if (v > 0)
+ dist = -dist;
+ if (snapMode != QDeclarativeGridView::SnapOneRow) {
+ qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist;
+ data.flickTarget = -snapPosAt(-dataValue + distTemp);
+ }
+ data.flickTarget = isRightToLeftTopToBottom() ? -data.flickTarget+size() : data.flickTarget;
+ if (overShoot) {
+ if (data.flickTarget >= minExtent) {
+ overshootDist = overShootDistance(vSize);
+ data.flickTarget += overshootDist;
+ } else if (data.flickTarget <= maxExtent) {
+ overshootDist = overShootDistance(vSize);
+ data.flickTarget -= overshootDist;
+ }
+ }
+ qreal adjDist = -data.flickTarget + data.move.value();
+ if (qAbs(adjDist) > qAbs(dist)) {
+ // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration
+ qreal adjv2 = accel * 2.0f * qAbs(adjDist);
+ if (adjv2 > v2) {
+ v2 = adjv2;
+ v = qSqrt(v2);
+ if (dist > 0)
+ v = -v;
+ }
+ }
+ dist = adjDist;
+ accel = v2 / (2.0f * qAbs(dist));
+ } else {
+ data.flickTarget = velocity > 0 ? minExtent : maxExtent;
+ overshootDist = overShoot ? overShootDistance(vSize) : 0;
+ }
+ timeline.reset(data.move);
+ timeline.accel(data.move, v, accel, maxDistance + overshootDist);
+ timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this));
+ if (!hData.flicking && q->xflick()) {
+ hData.flicking = true;
+ emit q->flickingChanged();
+ emit q->flickingHorizontallyChanged();
+ emit q->flickStarted();
+ }
+ if (!vData.flicking && q->yflick()) {
+ vData.flicking = true;
+ emit q->flickingChanged();
+ emit q->flickingVerticallyChanged();
+ emit q->flickStarted();
+ }
+ } else {
+ timeline.reset(data.move);
+ fixup(data, minExtent, maxExtent);
+ }
+}
+
+
+//----------------------------------------------------------------------------
+
+/*!
+ \qmlclass GridView QDeclarativeGridView
+ \since 4.7
+ \ingroup qml-view-elements
+
+ \inherits Flickable
+ \brief The GridView item provides a grid view of items provided by a model.
+
+ A GridView 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.
+
+ A GridView has a \l model, which defines the data to be displayed, and
+ a \l delegate, which defines how the data should be displayed. Items in a
+ GridView are laid out horizontally or vertically. Grid views are inherently flickable
+ as GridView inherits from \l Flickable.
+
+ \section1 Example Usage
+
+ The following example shows the definition of a simple list model defined
+ in a file called \c ContactModel.qml:
+
+ \snippet doc/src/snippets/declarative/gridview/ContactModel.qml 0
+
+ \div {class="float-right"}
+ \inlineimage gridview-simple.png
+ \enddiv
+
+ This model can be referenced as \c ContactModel in other QML files. See \l{QML Modules}
+ for more information about creating reusable components like this.
+
+ Another component can display this model data in a GridView, as in the following
+ example, which creates a \c ContactModel component for its model, and a \l Column element
+ (containing \l Image and \l Text elements) for its delegate.
+
+ \clearfloat
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml import
+ \codeline
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs simple
+
+ \div {class="float-right"}
+ \inlineimage gridview-highlight.png
+ \enddiv
+
+ The view will create a new delegate for each item in the model. Note that the delegate
+ is able to access the model's \c name and \c portrait data directly.
+
+ An improved grid view is shown below. The delegate is visually improved and is moved
+ into a separate \c contactDelegate component.
+
+ \clearfloat
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs advanced
+
+ The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
+ and \c focus is set to \c true to enable keyboard navigation for the grid view.
+ The grid 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.
+
+ GridView attaches a number of properties to the root item of the delegate, for example
+ \c {GridView.isCurrentItem}. In the following example, the root delegate item can access
+ this attached property directly as \c GridView.isCurrentItem, while the child
+ \c contactInfo object must refer to this property as \c wrapper.GridView.isCurrentItem.
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
+
+ \note Views do not set the \l{Item::}{clip} property automatically.
+ If the view is not clipped by another item or the screen, it will be necessary
+ to set this property to true in order to clip the items that are partially or
+ fully outside the view.
+
+ \sa {declarative/modelviews/gridview}{GridView example}
+*/
+QDeclarativeGridView::QDeclarativeGridView(QDeclarativeItem *parent)
+ : QDeclarativeFlickable(*(new QDeclarativeGridViewPrivate), parent)
+{
+ Q_D(QDeclarativeGridView);
+ d->init();
+}
+
+QDeclarativeGridView::~QDeclarativeGridView()
+{
+ Q_D(QDeclarativeGridView);
+ d->clear();
+ if (d->ownModel)
+ delete d->model;
+ delete d->header;
+ delete d->footer;
+}
+
+/*!
+ \qmlattachedproperty bool GridView::isCurrentItem
+ This attached property is true if this delegate is the current item; otherwise false.
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty GridView GridView::view
+ This attached property holds the view that manages this delegate instance.
+
+ It is attached to each instance of the delegate.
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
+*/
+
+/*!
+ \qmlattachedproperty bool GridView::delayRemove
+ This attached property holds whether the delegate may be destroyed.
+
+ It is attached to each instance of the delegate.
+
+ It is sometimes necessary to delay the destruction of an item
+ until an animation completes.
+
+ The example below ensures that the animation completes before
+ the item is removed from the grid.
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml delayRemove
+*/
+
+/*!
+ \qmlattachedsignal GridView::onAdd()
+ This attached handler is called immediately after an item is added to the view.
+*/
+
+/*!
+ \qmlattachedsignal GridView::onRemove()
+ This attached handler is called immediately before an item is removed from the view.
+*/
+
+
+/*!
+ \qmlproperty model GridView::model
+ This property holds the model providing data for the grid.
+
+ The model provides the set of data that is used to create the items
+ in the view. Models can be created directly in QML using \l ListModel, \l XmlListModel
+ or \l VisualItemModel, or provided by C++ model classes. If a C++ model class is
+ used, it must be a subclass of \l QAbstractItemModel or a simple list.
+
+ \sa {qmlmodels}{Data Models}
+*/
+QVariant QDeclarativeGridView::model() const
+{
+ Q_D(const QDeclarativeGridView);
+ return d->modelVariant;
+}
+
+// For internal use
+int QDeclarativeGridView::modelCount() const
+{
+ Q_D(const QDeclarativeGridView);
+ return d->model->count();
+}
+
+void QDeclarativeGridView::setModel(const QVariant &model)
+{
+ Q_D(QDeclarativeGridView);
+ if (d->modelVariant == model)
+ return;
+ if (d->model) {
+ disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+ disconnect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
+ }
+ d->clear();
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QDeclarativeVisualModel *vim = 0;
+ if (object && (vim = qobject_cast<QDeclarativeVisualModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QDeclarativeVisualDataModel(qmlContext(this), this);
+ d->ownModel = true;
+ }
+ if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model))
+ dataModel->setModel(model);
+ }
+ if (d->model) {
+ d->bufferMode = QDeclarativeGridViewPrivate::BufferBefore | QDeclarativeGridViewPrivate::BufferAfter;
+ if (isComponentComplete()) {
+ refill();
+ if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
+ setCurrentIndex(0);
+ } else {
+ d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
+ d->updateC