summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/easing/easing.cpp669
-rw-r--r--src/3rdparty/easing/legal.qdoc35
-rw-r--r--src/corelib/animation/animation.pri25
-rw-r--r--src/corelib/animation/qabstractanimation.cpp780
-rw-r--r--src/corelib/animation/qabstractanimation.h141
-rw-r--r--src/corelib/animation/qabstractanimation_p.h145
-rw-r--r--src/corelib/animation/qanimationgroup.cpp275
-rw-r--r--src/corelib/animation/qanimationgroup.h92
-rw-r--r--src/corelib/animation/qanimationgroup_p.h79
-rw-r--r--src/corelib/animation/qparallelanimationgroup.cpp298
-rw-r--r--src/corelib/animation/qparallelanimationgroup.h90
-rw-r--r--src/corelib/animation/qparallelanimationgroup_p.h85
-rw-r--r--src/corelib/animation/qpauseanimation.cpp139
-rw-r--r--src/corelib/animation/qpauseanimation.h88
-rw-r--r--src/corelib/animation/qpropertyanimation.cpp289
-rw-r--r--src/corelib/animation/qpropertyanimation.h93
-rw-r--r--src/corelib/animation/qpropertyanimation_p.h89
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.cpp572
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.h100
-rw-r--r--src/corelib/animation/qsequentialanimationgroup_p.h111
-rw-r--r--src/corelib/animation/qvariantanimation.cpp645
-rw-r--r--src/corelib/animation/qvariantanimation.h135
-rw-r--r--src/corelib/animation/qvariantanimation_p.h133
-rw-r--r--src/corelib/arch/qatomic_bootstrap.h14
-rw-r--r--src/corelib/corelib.pro2
-rw-r--r--src/corelib/global/qglobal.h29
-rw-r--r--src/corelib/kernel/kernel.pri18
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp34
-rw-r--r--src/corelib/kernel/qabstractitemmodel.h3
-rw-r--r--src/corelib/kernel/qabstractitemmodel_p.h5
-rw-r--r--src/corelib/kernel/qcoreevent.cpp4
-rw-r--r--src/corelib/kernel/qcoreevent.h8
-rw-r--r--src/corelib/kernel/qmetaobject.cpp89
-rw-r--r--src/corelib/kernel/qmetaobject.h3
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp2450
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h269
-rw-r--r--src/corelib/kernel/qobject.cpp17
-rw-r--r--src/corelib/kernel/qobject.h11
-rw-r--r--src/corelib/kernel/qobject_p.h20
-rw-r--r--src/corelib/kernel/qobjectdefs.h4
-rw-r--r--src/corelib/kernel/qvariant_p.h2
-rw-r--r--src/corelib/statemachine/qabstractstate.cpp230
-rw-r--r--src/corelib/statemachine/qabstractstate.h93
-rw-r--r--src/corelib/statemachine/qabstractstate_p.h93
-rw-r--r--src/corelib/statemachine/qabstracttransition.cpp371
-rw-r--r--src/corelib/statemachine/qabstracttransition.h114
-rw-r--r--src/corelib/statemachine/qabstracttransition_p.h99
-rw-r--r--src/corelib/statemachine/qeventtransition.cpp286
-rw-r--r--src/corelib/statemachine/qeventtransition.h102
-rw-r--r--src/corelib/statemachine/qeventtransition_p.h78
-rw-r--r--src/corelib/statemachine/qfinalstate.cpp134
-rw-r--r--src/corelib/statemachine/qfinalstate.h80
-rw-r--r--src/corelib/statemachine/qhistorystate.cpp228
-rw-r--r--src/corelib/statemachine/qhistorystate.h95
-rw-r--r--src/corelib/statemachine/qhistorystate_p.h80
-rw-r--r--src/corelib/statemachine/qsignalevent.h77
-rw-r--r--src/corelib/statemachine/qsignaleventgenerator_p.h85
-rw-r--r--src/corelib/statemachine/qsignaltransition.cpp261
-rw-r--r--src/corelib/statemachine/qsignaltransition.h93
-rw-r--r--src/corelib/statemachine/qsignaltransition_p.h78
-rw-r--r--src/corelib/statemachine/qstate.cpp481
-rw-r--r--src/corelib/statemachine/qstate.h117
-rw-r--r--src/corelib/statemachine/qstate_p.h108
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp2218
-rw-r--r--src/corelib/statemachine/qstatemachine.h173
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h224
-rw-r--r--src/corelib/statemachine/qwrappedevent.h76
-rw-r--r--src/corelib/statemachine/statemachine.pri30
-rw-r--r--src/corelib/tools/qeasingcurve.cpp844
-rw-r--r--src/corelib/tools/qeasingcurve.h114
-rw-r--r--src/corelib/tools/qtimeline.cpp114
-rw-r--r--src/corelib/tools/qtimeline.h7
-rw-r--r--src/corelib/tools/tools.pri2
-rw-r--r--src/declarative/3rdparty/3rdparty.pri5
-rw-r--r--src/declarative/3rdparty/qlistmodelinterface.cpp108
-rw-r--r--src/declarative/3rdparty/qlistmodelinterface.h86
-rw-r--r--src/declarative/canvas/canvas.pri19
-rw-r--r--src/declarative/canvas/qsimplecanvas.cpp1023
-rw-r--r--src/declarative/canvas/qsimplecanvas.h189
-rw-r--r--src/declarative/canvas/qsimplecanvas_graphicsview.cpp213
-rw-r--r--src/declarative/canvas/qsimplecanvas_opengl.cpp456
-rw-r--r--src/declarative/canvas/qsimplecanvas_opengl1.cpp401
-rw-r--r--src/declarative/canvas/qsimplecanvas_p.h197
-rw-r--r--src/declarative/canvas/qsimplecanvas_software.cpp195
-rw-r--r--src/declarative/canvas/qsimplecanvasfilter.cpp323
-rw-r--r--src/declarative/canvas/qsimplecanvasfilter.h113
-rw-r--r--src/declarative/canvas/qsimplecanvasfilter_p.h70
-rw-r--r--src/declarative/canvas/qsimplecanvasitem.cpp1868
-rw-r--r--src/declarative/canvas/qsimplecanvasitem.h303
-rw-r--r--src/declarative/canvas/qsimplecanvasitem_p.h263
-rw-r--r--src/declarative/canvas/qsimplecanvasserver.cpp107
-rw-r--r--src/declarative/canvas/qsimplecanvasserver_p.h71
-rw-r--r--src/declarative/debugger/debugger.pri13
-rw-r--r--src/declarative/debugger/qmlcanvasdebugger.cpp240
-rw-r--r--src/declarative/debugger/qmlcanvasdebugger_p.h89
-rw-r--r--src/declarative/debugger/qmldebugger.cpp361
-rw-r--r--src/declarative/debugger/qmldebugger.h106
-rw-r--r--src/declarative/debugger/qmldebuggerstatus.cpp54
-rw-r--r--src/declarative/debugger/qmldebuggerstatus.h67
-rw-r--r--src/declarative/debugger/qmlobjecttree.cpp75
-rw-r--r--src/declarative/debugger/qmlobjecttree_p.h86
-rw-r--r--src/declarative/debugger/qmlpropertyview.cpp224
-rw-r--r--src/declarative/debugger/qmlpropertyview_p.h78
-rw-r--r--src/declarative/debugger/qmlwatches.cpp304
-rw-r--r--src/declarative/debugger/qmlwatches_p.h100
-rw-r--r--src/declarative/declarative.pro30
-rw-r--r--src/declarative/extra/extra.pri24
-rw-r--r--src/declarative/extra/qfxintegermodel.cpp126
-rw-r--r--src/declarative/extra/qfxintegermodel.h86
-rw-r--r--src/declarative/extra/qmlnumberformatter.cpp215
-rw-r--r--src/declarative/extra/qmlnumberformatter.h92
-rw-r--r--src/declarative/extra/qmlsqlconnection.cpp437
-rw-r--r--src/declarative/extra/qmlsqlconnection.h117
-rw-r--r--src/declarative/extra/qmlsqlquery.cpp694
-rw-r--r--src/declarative/extra/qmlsqlquery.h143
-rw-r--r--src/declarative/extra/qmlxmllistmodel.cpp385
-rw-r--r--src/declarative/extra/qmlxmllistmodel.h141
-rw-r--r--src/declarative/extra/qnumberformat.cpp224
-rw-r--r--src/declarative/extra/qnumberformat.h172
-rw-r--r--src/declarative/fx/fx.pri95
-rw-r--r--src/declarative/fx/qfxanchors.cpp997
-rw-r--r--src/declarative/fx/qfxanchors.h198
-rw-r--r--src/declarative/fx/qfxanchors_p.h109
-rw-r--r--src/declarative/fx/qfxanimatedimageitem.cpp213
-rw-r--r--src/declarative/fx/qfxanimatedimageitem.h100
-rw-r--r--src/declarative/fx/qfxanimatedimageitem_p.h77
-rw-r--r--src/declarative/fx/qfxblendedimage.cpp297
-rw-r--r--src/declarative/fx/qfxblendedimage.h111
-rw-r--r--src/declarative/fx/qfxblurfilter.cpp467
-rw-r--r--src/declarative/fx/qfxblurfilter.h82
-rw-r--r--src/declarative/fx/qfxcomponentinstance.cpp152
-rw-r--r--src/declarative/fx/qfxcomponentinstance.h89
-rw-r--r--src/declarative/fx/qfxcomponentinstance_p.h76
-rw-r--r--src/declarative/fx/qfxcontentwrapper.cpp144
-rw-r--r--src/declarative/fx/qfxcontentwrapper.h90
-rw-r--r--src/declarative/fx/qfxcontentwrapper_p.h71
-rw-r--r--src/declarative/fx/qfxevents.cpp182
-rw-r--r--src/declarative/fx/qfxevents_p.h127
-rw-r--r--src/declarative/fx/qfxflickable.cpp1153
-rw-r--r--src/declarative/fx/qfxflickable.h195
-rw-r--r--src/declarative/fx/qfxflickable_p.h170
-rw-r--r--src/declarative/fx/qfxflipable.cpp349
-rw-r--r--src/declarative/fx/qfxflipable.h106
-rw-r--r--src/declarative/fx/qfxfocuspanel.cpp104
-rw-r--r--src/declarative/fx/qfxfocuspanel.h81
-rw-r--r--src/declarative/fx/qfxfocusrealm.cpp72
-rw-r--r--src/declarative/fx/qfxfocusrealm.h67
-rw-r--r--src/declarative/fx/qfxgridview.cpp1399
-rw-r--r--src/declarative/fx/qfxgridview.h146
-rw-r--r--src/declarative/fx/qfxhighlightfilter.cpp319
-rw-r--r--src/declarative/fx/qfxhighlightfilter.h98
-rw-r--r--src/declarative/fx/qfximage.cpp1009
-rw-r--r--src/declarative/fx/qfximage.h129
-rw-r--r--src/declarative/fx/qfximage_p.h119
-rw-r--r--src/declarative/fx/qfxitem.cpp2154
-rw-r--r--src/declarative/fx/qfxitem.h280
-rw-r--r--src/declarative/fx/qfxitem_p.h180
-rw-r--r--src/declarative/fx/qfxkeyactions.cpp920
-rw-r--r--src/declarative/fx/qfxkeyactions.h319
-rw-r--r--src/declarative/fx/qfxkeyproxy.cpp116
-rw-r--r--src/declarative/fx/qfxkeyproxy.h78
-rw-r--r--src/declarative/fx/qfxlayouts.cpp1082
-rw-r--r--src/declarative/fx/qfxlayouts.h171
-rw-r--r--src/declarative/fx/qfxlayouts_p.h100
-rw-r--r--src/declarative/fx/qfxlistview.cpp1629
-rw-r--r--src/declarative/fx/qfxlistview.h152
-rw-r--r--src/declarative/fx/qfxmouseregion.cpp580
-rw-r--r--src/declarative/fx/qfxmouseregion.h163
-rw-r--r--src/declarative/fx/qfxmouseregion_p.h110
-rw-r--r--src/declarative/fx/qfxpainteditem.cpp344
-rw-r--r--src/declarative/fx/qfxpainteditem.h97
-rw-r--r--src/declarative/fx/qfxpainteditem_p.h95
-rw-r--r--src/declarative/fx/qfxparticles.cpp1120
-rw-r--r--src/declarative/fx/qfxparticles.h240
-rw-r--r--src/declarative/fx/qfxpath.cpp865
-rw-r--r--src/declarative/fx/qfxpath.h257
-rw-r--r--src/declarative/fx/qfxpath_p.h79
-rw-r--r--src/declarative/fx/qfxpathview.cpp889
-rw-r--r--src/declarative/fx/qfxpathview.h136
-rw-r--r--src/declarative/fx/qfxpathview_p.h148
-rw-r--r--src/declarative/fx/qfxpixmap.cpp293
-rw-r--r--src/declarative/fx/qfxpixmap.h93
-rw-r--r--src/declarative/fx/qfxrect.cpp864
-rw-r--r--src/declarative/fx/qfxrect.h140
-rw-r--r--src/declarative/fx/qfxrect_p.h107
-rw-r--r--src/declarative/fx/qfxreflectionfilter.cpp352
-rw-r--r--src/declarative/fx/qfxreflectionfilter.h96
-rw-r--r--src/declarative/fx/qfxrepeater.cpp356
-rw-r--r--src/declarative/fx/qfxrepeater.h89
-rw-r--r--src/declarative/fx/qfxrepeater_p.h81
-rw-r--r--src/declarative/fx/qfxscalegrid.cpp216
-rw-r--r--src/declarative/fx/qfxscalegrid.h120
-rw-r--r--src/declarative/fx/qfxshadowfilter.cpp214
-rw-r--r--src/declarative/fx/qfxshadowfilter.h86
-rw-r--r--src/declarative/fx/qfxtext.cpp950
-rw-r--r--src/declarative/fx/qfxtext.h153
-rw-r--r--src/declarative/fx/qfxtext_p.h132
-rw-r--r--src/declarative/fx/qfxtextedit.cpp887
-rw-r--r--src/declarative/fx/qfxtextedit.h202
-rw-r--r--src/declarative/fx/qfxtextedit_p.h107
-rw-r--r--src/declarative/fx/qfxtransform.cpp865
-rw-r--r--src/declarative/fx/qfxtransform.h316
-rw-r--r--src/declarative/fx/qfxvisualitemmodel.cpp726
-rw-r--r--src/declarative/fx/qfxvisualitemmodel.h127
-rw-r--r--src/declarative/fx/qfxwebview.cpp1076
-rw-r--r--src/declarative/fx/qfxwebview.h216
-rw-r--r--src/declarative/fx/qfxwidgetcontainer.cpp108
-rw-r--r--src/declarative/fx/qfxwidgetcontainer.h79
-rw-r--r--src/declarative/opengl/glbasicshaders.cpp707
-rw-r--r--src/declarative/opengl/glbasicshaders.h244
-rw-r--r--src/declarative/opengl/glheaders.h49
-rw-r--r--src/declarative/opengl/glsave.cpp1
-rw-r--r--src/declarative/opengl/glsave.h111
-rw-r--r--src/declarative/opengl/gltexture.cpp322
-rw-r--r--src/declarative/opengl/gltexture.h116
-rw-r--r--src/declarative/opengl/opengl.pri20
-rw-r--r--src/declarative/qml/parser/javascript.g2809
-rw-r--r--src/declarative/qml/parser/javascriptast.cpp912
-rw-r--r--src/declarative/qml/parser/javascriptast_p.h2519
-rw-r--r--src/declarative/qml/parser/javascriptastfwd_p.h164
-rw-r--r--src/declarative/qml/parser/javascriptastvisitor.cpp58
-rw-r--r--src/declarative/qml/parser/javascriptastvisitor_p.h326
-rw-r--r--src/declarative/qml/parser/javascriptengine_p.cpp157
-rw-r--r--src/declarative/qml/parser/javascriptengine_p.h144
-rw-r--r--src/declarative/qml/parser/javascriptgrammar.cpp732
-rw-r--r--src/declarative/qml/parser/javascriptgrammar_p.h200
-rw-r--r--src/declarative/qml/parser/javascriptlexer.cpp1142
-rw-r--r--src/declarative/qml/parser/javascriptlexer_p.h250
-rw-r--r--src/declarative/qml/parser/javascriptmemorypool_p.h130
-rw-r--r--src/declarative/qml/parser/javascriptnodepool_p.h139
-rw-r--r--src/declarative/qml/parser/javascriptparser.cpp1658
-rw-r--r--src/declarative/qml/parser/javascriptparser_p.h216
-rw-r--r--src/declarative/qml/parser/javascriptprettypretty.cpp1334
-rw-r--r--src/declarative/qml/parser/javascriptprettypretty_p.h329
-rw-r--r--src/declarative/qml/parser/javascriptvalue.h6
-rw-r--r--src/declarative/qml/parser/parser.pri21
-rw-r--r--src/declarative/qml/qml.h119
-rw-r--r--src/declarative/qml/qml.pri73
-rw-r--r--src/declarative/qml/qmlbindablevalue.cpp237
-rw-r--r--src/declarative/qml/qmlbindablevalue.h94
-rw-r--r--src/declarative/qml/qmlbindablevalue_p.h66
-rw-r--r--src/declarative/qml/qmlboundsignal.cpp159
-rw-r--r--src/declarative/qml/qmlboundsignal_p.h104
-rw-r--r--src/declarative/qml/qmlclassfactory.cpp47
-rw-r--r--src/declarative/qml/qmlclassfactory_p.h63
-rw-r--r--src/declarative/qml/qmlcompiledcomponent.cpp96
-rw-r--r--src/declarative/qml/qmlcompiledcomponent_p.h79
-rw-r--r--src/declarative/qml/qmlcompiler.cpp1512
-rw-r--r--src/declarative/qml/qmlcompiler_p.h179
-rw-r--r--src/declarative/qml/qmlcomponent.cpp549
-rw-r--r--src/declarative/qml/qmlcomponent.h110
-rw-r--r--src/declarative/qml/qmlcomponent_p.h92
-rw-r--r--src/declarative/qml/qmlcompositetypemanager.cpp365
-rw-r--r--src/declarative/qml/qmlcompositetypemanager_p.h153
-rw-r--r--src/declarative/qml/qmlcontext.cpp500
-rw-r--r--src/declarative/qml/qmlcontext.h107
-rw-r--r--src/declarative/qml/qmlcontext_p.h104
-rw-r--r--src/declarative/qml/qmlcustomparser.cpp230
-rw-r--r--src/declarative/qml/qmlcustomparser_p.h111
-rw-r--r--src/declarative/qml/qmlcustomparser_p_p.h79
-rw-r--r--src/declarative/qml/qmldeclarativedata_p.h71
-rw-r--r--src/declarative/qml/qmldom.cpp1519
-rw-r--r--src/declarative/qml/qmldom.h274
-rw-r--r--src/declarative/qml/qmldom_p.h119
-rw-r--r--src/declarative/qml/qmlengine.cpp1566
-rw-r--r--src/declarative/qml/qmlengine.h109
-rw-r--r--src/declarative/qml/qmlengine_p.h289
-rw-r--r--src/declarative/qml/qmlerror.cpp228
-rw-r--r--src/declarative/qml/qmlerror.h82
-rw-r--r--src/declarative/qml/qmlexpression.h118
-rw-r--r--src/declarative/qml/qmlinfo.cpp99
-rw-r--r--src/declarative/qml/qmlinfo.h69
-rw-r--r--src/declarative/qml/qmlinstruction.cpp211
-rw-r--r--src/declarative/qml/qmlinstruction_p.h303
-rw-r--r--src/declarative/qml/qmllist.h127
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp1119
-rw-r--r--src/declarative/qml/qmlmetaproperty.h142
-rw-r--r--src/declarative/qml/qmlmetaproperty_p.h83
-rw-r--r--src/declarative/qml/qmlmetatype.cpp1144
-rw-r--r--src/declarative/qml/qmlmetatype.h274
-rw-r--r--src/declarative/qml/qmlparser.cpp335
-rw-r--r--src/declarative/qml/qmlparser_p.h281
-rw-r--r--src/declarative/qml/qmlparserstatus.cpp88
-rw-r--r--src/declarative/qml/qmlparserstatus.h76
-rw-r--r--src/declarative/qml/qmlprivate.cpp48
-rw-r--r--src/declarative/qml/qmlprivate.h365
-rw-r--r--src/declarative/qml/qmlpropertyvaluesource.cpp81
-rw-r--r--src/declarative/qml/qmlpropertyvaluesource.h79
-rw-r--r--src/declarative/qml/qmlproxymetaobject.cpp113
-rw-r--r--src/declarative/qml/qmlproxymetaobject_p.h85
-rw-r--r--src/declarative/qml/qmlrefcount.cpp66
-rw-r--r--src/declarative/qml/qmlrefcount_p.h69
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp736
-rw-r--r--src/declarative/qml/qmlscriptparser_p.h66
-rw-r--r--src/declarative/qml/qmlstringconverters.cpp212
-rw-r--r--src/declarative/qml/qmlstringconverters_p.h68
-rw-r--r--src/declarative/qml/qmlvme.cpp1361
-rw-r--r--src/declarative/qml/qmlvme_p.h74
-rw-r--r--src/declarative/qml/qmlvmemetaobject.cpp174
-rw-r--r--src/declarative/qml/qmlvmemetaobject_p.h75
-rw-r--r--src/declarative/qml/script/generator/generator.pro11
-rw-r--r--src/declarative/qml/script/generator/main.cpp135
-rw-r--r--src/declarative/qml/script/instructions.h32
-rw-r--r--src/declarative/qml/script/keywords.cpp89
-rw-r--r--src/declarative/qml/script/lexer.cpp139
-rw-r--r--src/declarative/qml/script/lexer.h54
-rw-r--r--src/declarative/qml/script/qmlbasicscript.cpp914
-rw-r--r--src/declarative/qml/script/qmlbasicscript.h76
-rw-r--r--src/declarative/qml/script/qmlbasicscript_p.h53
-rw-r--r--src/declarative/qml/script/script.pri11
-rw-r--r--src/declarative/qml/script/tokens.cpp43
-rw-r--r--src/declarative/qml/script/tokens.h36
-rw-r--r--src/declarative/test/qfxtestengine.cpp457
-rw-r--r--src/declarative/test/qfxtestengine.h85
-rw-r--r--src/declarative/test/qfxtestobjects.cpp348
-rw-r--r--src/declarative/test/qfxtestobjects.h212
-rw-r--r--src/declarative/test/qfxtestview.cpp79
-rw-r--r--src/declarative/test/qfxtestview.h74
-rw-r--r--src/declarative/test/test.pri9
-rw-r--r--src/declarative/timeline/qmltimeline.cpp940
-rw-r--r--src/declarative/timeline/qmltimeline.h190
-rw-r--r--src/declarative/timeline/qmltimelinevalueproxy.h86
-rw-r--r--src/declarative/timeline/timeline.pri7
-rw-r--r--src/declarative/util/qbindablemap.cpp182
-rw-r--r--src/declarative/util/qbindablemap.h87
-rw-r--r--src/declarative/util/qfxglobal.h124
-rw-r--r--src/declarative/util/qfxperf.cpp75
-rw-r--r--src/declarative/util/qfxperf.h87
-rw-r--r--src/declarative/util/qfxview.cpp514
-rw-r--r--src/declarative/util/qfxview.h112
-rw-r--r--src/declarative/util/qmlanimation.cpp2259
-rw-r--r--src/declarative/util/qmlanimation.h453
-rw-r--r--src/declarative/util/qmlanimation_p.h396
-rw-r--r--src/declarative/util/qmlbehaviour.cpp253
-rw-r--r--src/declarative/util/qmlbehaviour.h97
-rw-r--r--src/declarative/util/qmlbind.cpp203
-rw-r--r--src/declarative/util/qmlbind.h89
-rw-r--r--src/declarative/util/qmlconnection.cpp299
-rw-r--r--src/declarative/util/qmlconnection.h91
-rw-r--r--src/declarative/util/qmldatetimeformatter.cpp368
-rw-r--r--src/declarative/util/qmldatetimeformatter.h116
-rw-r--r--src/declarative/util/qmlfollow.cpp359
-rw-r--r--src/declarative/util/qmlfollow.h103
-rw-r--r--src/declarative/util/qmlfont.cpp147
-rw-r--r--src/declarative/util/qmlfont.h92
-rw-r--r--src/declarative/util/qmllistaccessor.cpp243
-rw-r--r--src/declarative/util/qmllistaccessor.h82
-rw-r--r--src/declarative/util/qmllistmodel.cpp566
-rw-r--r--src/declarative/util/qmllistmodel.h66
-rw-r--r--src/declarative/util/qmlnullablevalue_p.h67
-rw-r--r--src/declarative/util/qmlopenmetaobject.cpp211
-rw-r--r--src/declarative/util/qmlopenmetaobject.h89
-rw-r--r--src/declarative/util/qmlpackage.cpp148
-rw-r--r--src/declarative/util/qmlpackage.h86
-rw-r--r--src/declarative/util/qmlscript.cpp228
-rw-r--r--src/declarative/util/qmlscript.h80
-rw-r--r--src/declarative/util/qmlsetproperties.cpp257
-rw-r--r--src/declarative/util/qmlsetproperties.h83
-rw-r--r--src/declarative/util/qmlstate.cpp472
-rw-r--r--src/declarative/util/qmlstate.h174
-rw-r--r--src/declarative/util/qmlstate_p.h78
-rw-r--r--src/declarative/util/qmlstategroup.cpp306
-rw-r--r--src/declarative/util/qmlstategroup.h95
-rw-r--r--src/declarative/util/qmlstateoperations.cpp432
-rw-r--r--src/declarative/util/qmlstateoperations.h132
-rw-r--r--src/declarative/util/qmltransition.cpp285
-rw-r--r--src/declarative/util/qmltransition.h97
-rw-r--r--src/declarative/util/qperformancelog.cpp177
-rw-r--r--src/declarative/util/qperformancelog.h176
-rw-r--r--src/declarative/util/util.pri49
-rw-r--r--src/declarative/widgets/graphicslayouts.cpp323
-rw-r--r--src/declarative/widgets/graphicslayouts.h190
-rw-r--r--src/declarative/widgets/graphicswidgets.cpp173
-rw-r--r--src/declarative/widgets/graphicswidgets.h60
-rw-r--r--src/declarative/widgets/widgets.pri10
-rw-r--r--src/gui/animation/animation.pri3
-rw-r--r--src/gui/animation/qguivariantanimation.cpp80
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp252
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h19
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h12
-rw-r--r--src/gui/graphicsview/qgraphicslayout.h2
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem.h2
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.h2
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicswidget.h7
-rw-r--r--src/gui/gui.pro2
-rw-r--r--src/gui/kernel/qaction.h30
-rw-r--r--src/gui/kernel/qapplication.cpp6
-rw-r--r--src/gui/kernel/qevent.cpp41
-rw-r--r--src/gui/kernel/qevent.h5
-rw-r--r--src/gui/kernel/qevent_p.h6
-rw-r--r--src/gui/painting/qdrawhelper.cpp12
-rw-r--r--src/gui/painting/qdrawutil.cpp4
-rw-r--r--src/gui/painting/qpainterpath.cpp2
-rw-r--r--src/gui/statemachine/qbasickeyeventtransition.cpp177
-rw-r--r--src/gui/statemachine/qbasickeyeventtransition_p.h68
-rw-r--r--src/gui/statemachine/qbasicmouseeventtransition.cpp181
-rw-r--r--src/gui/statemachine/qbasicmouseeventtransition_p.h73
-rw-r--r--src/gui/statemachine/qguistatemachine.cpp534
-rw-r--r--src/gui/statemachine/qkeyeventtransition.cpp161
-rw-r--r--src/gui/statemachine/qkeyeventtransition.h60
-rw-r--r--src/gui/statemachine/qmouseeventtransition.cpp191
-rw-r--r--src/gui/statemachine/qmouseeventtransition.h66
-rw-r--r--src/gui/statemachine/statemachine.pri13
-rw-r--r--src/gui/widgets/qbuttongroup.cpp13
-rw-r--r--src/opengl/gl2paintengineex/qglshader_p.h2
-rw-r--r--src/opengl/opengl.pro4
-rw-r--r--src/opengl/qglextensions.cpp174
-rw-r--r--src/opengl/qglextensions_p.h134
-rw-r--r--src/opengl/qglpixmapfilter.cpp172
-rw-r--r--src/opengl/qglpixmapfilter_p.h29
-rw-r--r--src/opengl/qglshaderprogram.cpp2992
-rw-r--r--src/opengl/qglshaderprogram.h297
-rw-r--r--src/script/qscriptengine_p.cpp5
-rw-r--r--src/script/qscriptenginefwd_p.h1
-rw-r--r--src/script/qscriptextqobject.cpp35
-rw-r--r--src/src.pro4
-rw-r--r--src/tools/moc/generator.cpp16
-rw-r--r--src/tools/moc/keywords.cpp162
-rw-r--r--src/tools/moc/moc.cpp11
-rw-r--r--src/tools/moc/moc.h7
-rw-r--r--src/tools/moc/token.h1
-rw-r--r--src/tools/moc/util/generate_keywords.cpp1
-rw-r--r--src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp2
426 files changed, 110634 insertions, 428 deletions
diff --git a/src/3rdparty/easing/easing.cpp b/src/3rdparty/easing/easing.cpp
new file mode 100644
index 0000000..5bd3997
--- /dev/null
+++ b/src/3rdparty/easing/easing.cpp
@@ -0,0 +1,669 @@
+/*
+Disclaimer for Robert Penner's Easing Equations license:
+
+TERMS OF USE - EASING EQUATIONS
+
+Open source under the BSD License.
+
+Copyright © 2001 Robert Penner
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <QtCore/qmath.h>
+#include <math.h>
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_PI_2
+#define M_PI_2 (M_PI / 2)
+#endif
+
+
+/**
+ * Easing equation function for a simple linear tweening, with no easing.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeNone(qreal progress)
+{
+ return progress;
+}
+
+/**
+ * Easing equation function for a quadratic (t^2) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInQuad(qreal t)
+{
+ return t*t;
+}
+
+/**
+* Easing equation function for a quadratic (t^2) easing out: decelerating to zero velocity.
+*
+* @param t Current time (in frames or seconds).
+* @return The correct value.
+*/
+static qreal easeOutQuad(qreal t)
+{
+ return -t*(t-2);
+}
+
+/**
+ * Easing equation function for a quadratic (t^2) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutQuad(qreal t)
+{
+ t*=2.0;
+ if (t < 1) {
+ return t*t/qreal(2);
+ } else {
+ --t;
+ return -0.5 * (t*(t-2) - 1);
+ }
+}
+
+/**
+ * Easing equation function for a quadratic (t^2) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInQuad(qreal t)
+{
+ if (t < 0.5) return easeOutQuad (t*2)/2;
+ return easeInQuad((2*t)-1)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for a cubic (t^3) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInCubic(qreal t)
+{
+ return t*t*t;
+}
+
+/**
+ * Easing equation function for a cubic (t^3) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutCubic(qreal t)
+{
+ t-=1.0;
+ return t*t*t + 1;
+}
+
+/**
+ * Easing equation function for a cubic (t^3) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutCubic(qreal t)
+{
+ t*=2.0;
+ if(t < 1) {
+ return 0.5*t*t*t;
+ } else {
+ t -= qreal(2.0);
+ return 0.5*(t*t*t + 2);
+ }
+}
+
+/**
+ * Easing equation function for a cubic (t^3) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInCubic(qreal t)
+{
+ if (t < 0.5) return easeOutCubic (2*t)/2;
+ return easeInCubic(2*t - 1)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for a quartic (t^4) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInQuart(qreal t)
+{
+ return t*t*t*t;
+}
+
+/**
+ * Easing equation function for a quartic (t^4) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutQuart(qreal t)
+{
+ t-= qreal(1.0);
+ return - (t*t*t*t- 1);
+}
+
+/**
+ * Easing equation function for a quartic (t^4) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutQuart(qreal t)
+{
+ t*=2;
+ if (t < 1) return 0.5*t*t*t*t;
+ else {
+ t -= 2.0f;
+ return -0.5 * (t*t*t*t- 2);
+ }
+}
+
+/**
+ * Easing equation function for a quartic (t^4) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInQuart(qreal t)
+{
+ if (t < 0.5) return easeOutQuart (2*t)/2;
+ return easeInQuart(2*t-1)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for a quintic (t^5) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInQuint(qreal t)
+{
+ return t*t*t*t*t;
+}
+
+/**
+ * Easing equation function for a quintic (t^5) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutQuint(qreal t)
+{
+ t-=1.0;
+ return t*t*t*t*t + 1;
+}
+
+/**
+ * Easing equation function for a quintic (t^5) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutQuint(qreal t)
+{
+ t*=2.0;
+ if (t < 1) return 0.5*t*t*t*t*t;
+ else {
+ t -= 2.0;
+ return 0.5*(t*t*t*t*t + 2);
+ }
+}
+
+/**
+ * Easing equation function for a quintic (t^5) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInQuint(qreal t)
+{
+ if (t < 0.5) return easeOutQuint (2*t)/2;
+ return easeInQuint(2*t - 1)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for a sinusoidal (sin(t)) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInSine(qreal t)
+{
+ return (t == 1.0) ? 1.0 : -::cos(t * M_PI_2) + 1.0;
+}
+
+/**
+ * Easing equation function for a sinusoidal (sin(t)) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutSine(qreal t)
+{
+ return ::sin(t* M_PI_2);
+}
+
+/**
+ * Easing equation function for a sinusoidal (sin(t)) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutSine(qreal t)
+{
+ return -0.5 * (::cos(M_PI*t) - 1);
+}
+
+/**
+ * Easing equation function for a sinusoidal (sin(t)) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInSine(qreal t)
+{
+ if (t < 0.5) return easeOutSine (2*t)/2;
+ return easeInSine(2*t - 1)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for an exponential (2^t) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInExpo(qreal t)
+{
+ return (t==0 || t == 1.0) ? t : ::qPow(2.0, 10 * (t - 1)) - qreal(0.001);
+}
+
+/**
+ * Easing equation function for an exponential (2^t) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutExpo(qreal t)
+{
+ return (t==1.0) ? 1.0 : 1.001 * (-::qPow(2.0f, -10 * t) + 1);
+}
+
+/**
+ * Easing equation function for an exponential (2^t) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutExpo(qreal t)
+{
+ if (t==0.0) return qreal(0.0);
+ if (t==1.0) return qreal(1.0);
+ t*=2.0;
+ if (t < 1) return 0.5 * ::qPow(qreal(2.0), 10 * (t - 1)) - 0.0005;
+ return 0.5 * 1.0005 * (-::qPow(qreal(2.0), -10 * (t - 1)) + 2);
+}
+
+/**
+ * Easing equation function for an exponential (2^t) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInExpo(qreal t)
+{
+ if (t < 0.5) return easeOutExpo (2*t)/2;
+ return easeInExpo(2*t - 1)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for a circular (sqrt(1-t^2)) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInCirc(qreal t)
+{
+ return -(::sqrt(1 - t*t) - 1);
+}
+
+/**
+ * Easing equation function for a circular (sqrt(1-t^2)) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutCirc(qreal t)
+{
+ t-= qreal(1.0);
+ return ::sqrt(1 - t* t);
+}
+
+/**
+ * Easing equation function for a circular (sqrt(1-t^2)) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutCirc(qreal t)
+{
+ t*=qreal(2.0);
+ if (t < 1) {
+ return -0.5 * (::sqrt(1 - t*t) - 1);
+ } else {
+ t -= qreal(2.0);
+ return 0.5 * (::sqrt(1 - t*t) + 1);
+ }
+}
+
+/**
+ * Easing equation function for a circular (sqrt(1-t^2)) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInCirc(qreal t)
+{
+ if (t < 0.5) return easeOutCirc (2*t)/2;
+ return easeInCirc(2*t - 1)/2 + 0.5;
+}
+
+static qreal easeInElastic_helper(qreal t, qreal b, qreal c, qreal d, qreal a, qreal p)
+{
+ if (t==0) return b;
+ qreal t_adj = (qreal)t / (qreal)d;
+ if (t_adj==1) return b+c;
+
+ qreal s;
+ if(a < ::fabs(c)) {
+ a = c;
+ s = p / 4.0f;
+ } else {
+ s = p / (2 * M_PI) * ::asin(c / a);
+ }
+
+ t_adj -= 1.0f;
+ return -(a*::qPow(2.0f,10*t_adj) * ::sin( (t_adj*d-s)*(2*M_PI)/p )) + b;
+}
+
+/**
+ * Easing equation function for an elastic (exponentially decaying sine wave) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @param p Period.
+ * @return The correct value.
+ */
+static qreal easeInElastic(qreal t, qreal a, qreal p)
+{
+ return easeInElastic_helper(t, 0, 1, 1, a, p);
+}
+
+static qreal easeOutElastic_helper(qreal t, qreal /*b*/, qreal c, qreal /*d*/, qreal a, qreal p)
+{
+ if (t==0) return 0;
+ if (t==1) return c;
+
+ qreal s;
+ if(a < c) {
+ a = c;
+ s = p / 4.0f;
+ } else {
+ s = p / (2 * M_PI) * ::asin(c / a);
+ }
+
+ return (a*::qPow(2.0f,-10*t) * ::sin( (t-s)*(2*M_PI)/p ) + c);
+}
+
+/**
+ * Easing equation function for an elastic (exponentially decaying sine wave) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @param p Period.
+ * @return The correct value.
+ */
+static qreal easeOutElastic(qreal t, qreal a, qreal p)
+{
+ return easeOutElastic_helper(t, 0, 1, 1, a, p);
+}
+
+/**
+ * Easing equation function for an elastic (exponentially decaying sine wave) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @param p Period.
+ * @return The correct value.
+ */
+static qreal easeInOutElastic(qreal t, qreal a, qreal p)
+{
+ if (t==0) return 0.0;
+ t*=2.0;
+ if (t==2) return 1.0;
+
+ qreal s;
+ if(a < 1.0) {
+ a = 1.0;
+ s = p / 4.0f;
+ } else {
+ s = p / (2 * M_PI) * ::asin(1.0 / a);
+ }
+
+ if (t < 1) return -.5*(a*::qPow(2.0f,10*(t-1)) * ::sin( (t-1-s)*(2*M_PI)/p ));
+ return a*::qPow(2.0f,-10*(t-1)) * ::sin( (t-1-s)*(2*M_PI)/p )*.5 + 1.0;
+}
+
+/**
+ * Easing equation function for an elastic (exponentially decaying sine wave) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @param p Period.
+ * @return The correct value.
+ */
+static qreal easeOutInElastic(qreal t, qreal a, qreal p)
+{
+ if (t < 0.5) return easeOutElastic_helper(t*2, 0, 0.5, 1.0, a, p);
+ return easeInElastic_helper(2*t - 1.0, 0.5, 0.5, 1.0, a, p);
+}
+
+/**
+ * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param s Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
+ * @return The correct value.
+ */
+static qreal easeInBack(qreal t, qreal s)
+{
+ return t*t*((s+1)*t - s);
+}
+
+/**
+ * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param s Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
+ * @return The correct value.
+ */
+static qreal easeOutBack(qreal t, qreal s)
+{
+ t-= qreal(1.0);
+ return t*t*((s+1)*t+ s) + 1;
+}
+
+/**
+ * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param s Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
+ * @return The correct value.
+ */
+static qreal easeInOutBack(qreal t, qreal s)
+{
+ t *= 2.0;
+ if (t < 1) {
+ s *= 1.525f;
+ return 0.5*(t*t*((s+1)*t - s));
+ } else {
+ t -= 2;
+ s *= 1.525f;
+ return 0.5*(t*t*((s+1)*t+ s) + 2);
+ }
+}
+
+/**
+ * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param s Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
+ * @return The correct value.
+ */
+static qreal easeOutInBack(qreal t, qreal s)
+{
+ if (t < 0.5) return easeOutBack (2*t, s)/2;
+ return easeInBack(2*t - 1, s)/2 + 0.5;
+}
+
+static qreal easeOutBounce_helper(qreal t, qreal c, qreal a)
+{
+ if (t == 1.0) return c;
+ if (t < (4/11.0)) {
+ return c*(7.5625*t*t);
+ } else if (t < (8/11.0)) {
+ t -= (6/11.0);
+ return -a * (1. - (7.5625*t*t + .75)) + c;
+ } else if (t < (10/11.0)) {
+ t -= (9/11.0);
+ return -a * (1. - (7.5625*t*t + .9375)) + c;
+ } else {
+ t -= (21/22.0);
+ return -a * (1. - (7.5625*t*t + .984375)) + c;
+ }
+}
+
+/**
+ * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @return The correct value.
+ */
+static qreal easeOutBounce(qreal t, qreal a)
+{
+ return easeOutBounce_helper(t, 1, a);
+}
+
+/**
+ * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @return The correct value.
+ */
+static qreal easeInBounce(qreal t, qreal a)
+{
+ return 1.0 - easeOutBounce_helper(1.0-t, 1.0, a);
+}
+
+
+/**
+ * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @return The correct value.
+ */
+static qreal easeInOutBounce(qreal t, qreal a)
+{
+ if (t < 0.5) return easeInBounce (2*t, a)/2;
+ else return (t == 1.0) ? 1.0 : easeOutBounce (2*t - 1, a)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @return The correct value.
+ */
+static qreal easeOutInBounce(qreal t, qreal a)
+{
+ if (t < 0.5) return easeOutBounce_helper(t*2, 0.5, a);
+ return 1.0 - easeOutBounce_helper (2.0-2*t, 0.5, a);
+}
+
+static inline qreal qt_sinProgress(qreal value)
+{
+ return qSin((value * M_PI) - M_PI_2) / 2 + qreal(0.5);
+}
+
+static inline qreal qt_smoothBeginEndMixFactor(qreal value)
+{
+ return qMin(qMax(1 - value * 2 + qreal(0.3), qreal(0.0)), qreal(1.0));
+}
+
+// SmoothBegin blends Smooth and Linear Interpolation.
+// Progress 0 - 0.3 : Smooth only
+// Progress 0.3 - ~ 0.5 : Mix of Smooth and Linear
+// Progress ~ 0.5 - 1 : Linear only
+
+/**
+ * Easing function that starts growing slowly, then increases in speed. At the end of the curve the speed will be constant.
+ */
+static qreal easeInCurve(qreal t)
+{
+ const qreal sinProgress = qt_sinProgress(t);
+ const qreal mix = qt_smoothBeginEndMixFactor(t);
+ return sinProgress * mix + t * (1 - mix);
+}
+
+/**
+ * Easing function that starts growing steadily, then ends slowly. The speed will be constant at the beginning of the curve.
+ */
+static qreal easeOutCurve(qreal t)
+{
+ const qreal sinProgress = qt_sinProgress(t);
+ const qreal mix = qt_smoothBeginEndMixFactor(1 - t);
+ return sinProgress * mix + t * (1 - mix);
+}
+
+/**
+ * Easing function where the value grows sinusoidally. Note that the calculated end value will be 0 rather than 1.
+ */
+static qreal easeSineCurve(qreal t)
+{
+ return (qSin(((t * M_PI * 2)) - M_PI_2) + 1) / 2;
+}
+
+/**
+ * Easing function where the value grows cosinusoidally. Note that the calculated start value will be 0.5 and the end value will be 0.5
+ * contrary to the usual 0 to 1 easing curve.
+ */
+static qreal easeCosineCurve(qreal t)
+{
+ return (qCos(((t * M_PI * 2)) - M_PI_2) + 1) / 2;
+}
+
diff --git a/src/3rdparty/easing/legal.qdoc b/src/3rdparty/easing/legal.qdoc
new file mode 100644
index 0000000..1be5f66
--- /dev/null
+++ b/src/3rdparty/easing/legal.qdoc
@@ -0,0 +1,35 @@
+/*!
+\page legal-easing.html
+\title Easing Equations by Robert Penner
+\ingroup group_animation
+
+\legalese
+\code
+Copyright (c) 2001 Robert Penner
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the author nor the names of contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\endcode
+\endlegalese
+*/
diff --git a/src/corelib/animation/animation.pri b/src/corelib/animation/animation.pri
new file mode 100644
index 0000000..cb7850c
--- /dev/null
+++ b/src/corelib/animation/animation.pri
@@ -0,0 +1,25 @@
+# Qt core animation module
+
+HEADERS += \
+ animation/qabstractanimation.h \
+ animation/qabstractanimation_p.h \
+ animation/qvariantanimation.h \
+ animation/qvariantanimation_p.h \
+ animation/qpropertyanimation.h \
+ animation/qpropertyanimation_p.h \
+ animation/qanimationgroup.h \
+ animation/qanimationgroup_p.h \
+ animation/qsequentialanimationgroup.h \
+ animation/qsequentialanimationgroup_p.h \
+ animation/qparallelanimationgroup.h \
+ animation/qparallelanimationgroup_p.h \
+ animation/qpauseanimation.h
+
+SOURCES += \
+ animation/qabstractanimation.cpp \
+ animation/qvariantanimation.cpp \
+ animation/qpropertyanimation.cpp \
+ animation/qanimationgroup.cpp \
+ animation/qsequentialanimationgroup.cpp \
+ animation/qparallelanimationgroup.cpp \
+ animation/qpauseanimation.cpp
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
new file mode 100644
index 0000000..6328d04
--- /dev/null
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -0,0 +1,780 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QAbstractAnimation
+ \ingroup group_animation
+ \brief The QAbstractAnimation class is the base of all animations.
+ \since 4.5
+ \preliminary
+
+ The class defines the functions for the functionality shared by
+ all animations. By inheriting this class, you can create custom
+ animations that plug into the rest of the animation framework.
+
+ The progress of an animation is given by its current time
+ (currentTime()), which is measured in milliseconds from the start
+ of the animation (0) to its end (duration()). The value is updated
+ automatically while the animation is running. It can also be set
+ directly with setCurrentTime().
+
+ At any point an animation is in one of three states:
+ \l{QAbstractAnimation::}{Running},
+ \l{QAbstractAnimation::}{Stopped}, or
+ \l{QAbstractAnimation::}{Paused}--as defined by the
+ \l{QAbstractAnimation::}{State} enum. The current state can be
+ changed by calling start(), stop(), pause(), or resume(). An
+ animation will always reset its \l{currentTime()}{current time}
+ when it is started. If paused, it will continue with the same
+ current time when resumed. When an animation is stopped, it cannot
+ be resumed, but will keep its current time (until started again).
+ QAbstractAnimation will emit stateChanged() whenever its state
+ changes.
+
+ An animation can loop any number of times by setting the loopCount
+ property. When an animation's current time reaches its duration(),
+ it will reset the current time and keep running. A loop count of 1
+ (the default value) means that the animation will run one time.
+ Note that a duration of -1 means that the animation will run until
+ stopped; the current time will increase indefinitely. When the
+ current time equals duration() and the animation is in its
+ final loop, the \l{QAbstractAnimation::}{Stopped} state is
+ entered, and the finished() signal is emitted.
+
+ QAbstractAnimation provides pure virtual functions used by
+ subclasses to track the progress of the animation: duration() and
+ updateCurrentTime(). The duration() function lets you report a
+ duration for the animation (as discussed above). The current time
+ is delivered by the animation framework through calls to
+ updateCurrentTime(). By reimplementing this function, you can
+ track the animation progress. Note that neither the interval
+ between calls nor the number of calls to this function are
+ defined; though, it will normally be 60 updates per second.
+
+ By reimplementing updateState(), you can track the animation's
+ state changes, which is particularly useful for animations that
+ are not driven by time.
+
+ \sa QVariantAnimation, QPropertyAnimation, QAnimationGroup, {The Animation Framework}
+*/
+
+/*!
+ \enum QAbstractAnimation::DeletionPolicy
+
+ \value KeepWhenStopped The animation will not be deleted when stopped.
+ \value DeleteWhenStopped The animation will be automatically deleted when
+ stopped.
+*/
+
+/*!
+ \fn QAbstractAnimation::finished()
+
+ QAbstractAnimation emits this signal after the animation has stopped and
+ has reached the end.
+
+ This signal is emitted after stateChanged().
+
+ \sa stateChanged()
+*/
+
+/*!
+ \fn QAbstractAnimation::stateChanged(QAbstractAnimation::State oldState, QAbstractAnimation::State newState)
+
+ QAbstractAnimation emits this signal whenever the state of the animation has
+ changed from \a oldState to \a newState. This signal is emitted after the virtual
+ updateState() function is called.
+
+ \sa updateState()
+*/
+
+/*!
+ \fn QAbstractAnimation::currentLoopChanged(int currentLoop)
+
+ QAbstractAnimation emits this signal whenever the current loop
+ changes. \a currentLoop is the current loop.
+
+ \sa currentLoop(), loopCount()
+*/
+
+/*!
+ \fn QAbstractAnimation::directionChanged(QAbstractAnimation::Direction newDirection);
+
+ QAbstractAnimation emits this signal whenever the direction has been
+ changed. \a newDirection is the new direction.
+
+ \sa direction
+*/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qabstractanimation.h"
+#include "qanimationgroup.h"
+#include <QtCore/qdebug.h>
+
+#include "qabstractanimation_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtCore/qthreadstorage.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qpointer.h>
+
+#define DEFAULT_TIMER_INTERVAL 16
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer);
+
+QUnifiedTimer::QUnifiedTimer() : QObject(), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), consistentTiming(false)
+{
+}
+
+QUnifiedTimer *QUnifiedTimer::instance()
+{
+ QUnifiedTimer *inst;
+ if (!unifiedTimer()->hasLocalData()) {
+ inst = new QUnifiedTimer;
+ unifiedTimer()->setLocalData(inst);
+ } else {
+ inst = unifiedTimer()->localData();
+ }
+ return inst;
+}
+
+void QUnifiedTimer::updateRecentlyStartedAnimations()
+{
+ if (animationsToStart.isEmpty())
+ return;
+
+ animations += animationsToStart;
+ updateTimer(); //we make sure we start the timer there
+
+ animationsToStart.clear();
+}
+
+/*
+ defines the timing interval. Default is DEFAULT_TIMER_INTERVAL
+*/
+void QUnifiedTimer::setTimingInterval(int interval)
+{
+ timingInterval = interval;
+ if (animationTimer.isActive()) {
+ //we changed the timing interval
+ animationTimer.start(timingInterval, this);
+ }
+}
+
+/*
+ this allows to have a consistent timer interval at each tick from the timer
+ not taking the real time that passed into account.
+*/
+void QUnifiedTimer::setConsistentTiming(bool b)
+{
+ consistentTiming = b;
+}
+
+int QUnifiedTimer::elapsedTime() const
+{
+ return lastTick;
+}
+
+void QUnifiedTimer::timerEvent(QTimerEvent *event)
+{
+ //this is simply the time we last received a tick
+ const int oldLastTick = lastTick;
+ if (time.isValid())
+ lastTick = consistentTiming ? oldLastTick + timingInterval : time.elapsed();
+
+ //we transfer the waiting animations into the "really running" state
+ updateRecentlyStartedAnimations();
+
+ if (event->timerId() == startStopAnimationTimer.timerId()) {
+ startStopAnimationTimer.stop();
+ if (animations.isEmpty()) {
+ animationTimer.stop();
+ time = QTime();
+ } else {
+ animationTimer.start(timingInterval, this);
+ lastTick = 0;
+ time.start();
+ }
+ } else if (event->timerId() == animationTimer.timerId()) {
+ const int delta = lastTick - oldLastTick;
+ for (int i = 0; i < animations.count(); ++i) {
+ QAbstractAnimation *animation = animations.at(i);
+ int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
+ + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
+ animation->setCurrentTime(elapsed);
+ }
+ }
+}
+
+void QUnifiedTimer::updateTimer()
+{
+ //we delay the call to start and stop for the animation timer so that if you
+ //stop and start animations in batch you don't stop/start the timer too often.
+ if (!startStopAnimationTimer.isActive())
+ startStopAnimationTimer.start(0, this); // we delay the actual start of the animation
+}
+
+void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation)
+{
+ if (animations.contains(animation) ||animationsToStart.contains(animation))
+ return;
+ animationsToStart << animation;
+ updateTimer();
+}
+
+void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
+{
+ animations.removeAll(animation);
+ animationsToStart.removeAll(animation);
+ updateTimer();
+}
+
+
+void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
+{
+ Q_Q(QAbstractAnimation);
+ if (state == newState)
+ return;
+
+ QAbstractAnimation::State oldState = state;
+ int oldCurrentTime = currentTime;
+ int oldCurrentLoop = currentLoop;
+ QAbstractAnimation::Direction oldDirection = direction;
+
+ state = newState;
+
+ QPointer<QAbstractAnimation> guard(q);
+
+ guard->updateState(oldState, newState);
+
+ //this is to be safe if updateState changes the state
+ if (state == oldState)
+ return;
+
+ // Notify state change
+ if (guard)
+ emit guard->stateChanged(oldState, newState);
+
+ // Enter running state.
+ switch (state)
+ {
+ case QAbstractAnimation::Paused:
+ case QAbstractAnimation::Running:
+ {
+ // Rewind
+ if (oldState == QAbstractAnimation::Stopped) {
+ if (guard) {
+ if (direction == QAbstractAnimation::Forward)
+ q->setCurrentTime(0);
+ else
+ q->setCurrentTime(loopCount == -1 ? q->duration() : q->totalDuration());
+ }
+
+ // Check if the setCurrentTime() function called stop().
+ // This can happen for a 0-duration animation
+ if (state == QAbstractAnimation::Stopped)
+ return;
+ }
+
+ // Register timer if our parent is not running.
+ if (state == QAbstractAnimation::Running && guard) {
+ if (!group || group->state() == QAbstractAnimation::Stopped) {
+ QUnifiedTimer::instance()->registerAnimation(q);
+ }
+ } else {
+ //new state is paused
+ QUnifiedTimer::instance()->unregisterAnimation(q);
+ }
+ }
+ break;
+ case QAbstractAnimation::Stopped:
+ // Leave running state.
+ int dura = q->duration();
+ if (deleteWhenStopped && guard)
+ q->deleteLater();
+
+ QUnifiedTimer::instance()->unregisterAnimation(q);
+
+ if (dura == -1 || loopCount < 0
+ || (oldDirection == QAbstractAnimation::Forward && (oldCurrentTime * (oldCurrentLoop + 1)) == (dura * loopCount))
+ || (oldDirection == QAbstractAnimation::Backward && oldCurrentTime == 0)) {
+ if (guard)
+ emit q->finished();
+ }
+ break;
+ }
+
+}
+
+/*!
+ Constructs the QAbstractAnimation base class, and passes \a parent to
+ QObject's constructor.
+
+ \sa QVariantAnimation, QAnimationGroup
+*/
+#ifdef QT_EXPERIMENTAL_SOLUTION
+QAbstractAnimation::QAbstractAnimation(QObject *parent)
+ : d_ptr(new QAbstractAnimationPrivate)
+{
+ // Allow auto-add on reparent
+ setParent(parent);
+ d_ptr->q_ptr = this;
+}
+#else
+QAbstractAnimation::QAbstractAnimation(QObject *parent)
+ : QObject(*new QAbstractAnimationPrivate, 0)
+{
+ // Allow auto-add on reparent
+ setParent(parent);
+}
+#endif
+
+/*!
+ \internal
+*/
+#ifdef QT_EXPERIMENTAL_SOLUTION
+QAbstractAnimation::QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent)
+ : d_ptr(&dd)
+{
+ // Allow auto-add on reparent
+ setParent(parent);
+ d_ptr->q_ptr = this;
+}
+#else
+QAbstractAnimation::QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent)
+ : QObject(dd, 0)
+{
+ // Allow auto-add on reparent
+ setParent(parent);
+}
+#endif
+
+/*!
+ Stops the animation if it's running, then destroys the
+ QAbstractAnimation. If the animation is part of a QAnimationGroup, it is
+ automatically removed before it's destroyed.
+*/
+QAbstractAnimation::~QAbstractAnimation()
+{
+ Q_D(QAbstractAnimation);
+ //we can't call stop here. Otherwise we get pure virtual calls
+ if (d->state != Stopped) {
+ QAbstractAnimation::State oldState = d->state;
+ d->state = Stopped;
+ emit stateChanged(oldState, d->state);
+ QUnifiedTimer::instance()->unregisterAnimation(this);
+ }
+}
+
+/*!
+ \property QAbstractAnimation::state
+ \brief state of the animation.
+
+ This property describes the current state of the animation. When the
+ animation state changes, QAbstractAnimation emits the stateChanged()
+ signal.
+*/
+QAbstractAnimation::State QAbstractAnimation::state() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->state;
+}
+
+/*!
+ If this animation is part of a QAnimationGroup, this function returns a
+ pointer to the group; otherwise, it returns 0.
+
+ \sa QAnimationGroup::addAnimation()
+*/
+QAnimationGroup *QAbstractAnimation::group() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->group;
+}
+
+/*!
+ \enum QAbstractAnimation::State
+
+ This enum describes the state of the animation.
+
+ \value Stopped The animation is not running. This is the initial state
+ of QAbstractAnimation, and the state QAbstractAnimation reenters when finished. The current
+ time remain unchanged until either setCurrentTime() is
+ called, or the animation is started by calling start().
+
+ \value Paused The animation is paused (i.e., temporarily
+ suspended). Calling resume() will resume animation activity.
+
+ \value Running The animation is running. While control is in the event
+ loop, QAbstractAnimation will update its current time at regular intervals,
+ calling updateCurrentTime() when appropriate.
+
+ \sa state(), stateChanged()
+*/
+
+/*!
+ \enum QAbstractAnimation::Direction
+
+ This enum describes the direction of the animation when in \l Running state.
+
+ \value Forward The current time of the animation increases with time (i.e.,
+ moves from 0 and towards the end / duration).
+
+ \value Backward The current time of the animation decreases with time (i.e.,
+ moves from the end / duration and towards 0).
+
+ \sa direction
+*/
+
+/*!
+ \property QAbstractAnimation::direction
+ \brief the direction of the animation when it is in \l Running
+ state.
+
+ This direction indicates whether the time moves from 0 towards the
+ animation duration, or from the value of the duration and towards 0 after
+ start() has been called.
+
+ By default, this property is set to \l Forward.
+*/
+QAbstractAnimation::Direction QAbstractAnimation::direction() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->direction;
+}
+void QAbstractAnimation::setDirection(Direction direction)
+{
+ Q_D(QAbstractAnimation);
+ if (d->direction == direction)
+ return;
+
+ d->direction = direction;
+ if (state() == Stopped) {
+ if (direction == Backward) {
+ d->currentTime = duration();
+ d->currentLoop = d->loopCount - 1;
+ } else {
+ d->currentTime = 0;
+ d->currentLoop = 0;
+ }
+ }
+ updateDirection(direction);
+ emit directionChanged(direction);
+}
+
+/*!
+ \property QAbstractAnimation::duration
+ \brief the duration of the animation.
+
+ If the duration is -1, it means that the duration is undefined.
+ In this case, loopCount is ignored.
+*/
+
+/*!
+ \property QAbstractAnimation::loopCount
+ \brief the loop count of the animation
+
+ This property describes the loop count of the animation as an integer.
+ By default this value is 1, indicating that the animation
+ should run once only, and then stop. By changing it you can let the
+ animation loop several times. With a value of 0, the animation will not
+ run at all, and with a value of -1, the animation will loop forever
+ until stopped.
+ It is not supported to have loop on an animation that has an undefined
+ duration. It will only run once.
+*/
+int QAbstractAnimation::loopCount() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->loopCount;
+}
+void QAbstractAnimation::setLoopCount(int loopCount)
+{
+ Q_D(QAbstractAnimation);
+ d->loopCount = loopCount;
+}
+
+/*!
+ \property QAbstractAnimation::currentLoop
+ \brief the current loop of the animation
+
+ This property describes the current loop of the animation. By default,
+ the animation's loop count is 1, and so the current loop will
+ always be 0. If the loop count is 2 and the animation runs past its
+ duration, it will automatically rewind and restart at current time 0, and
+ current loop 1, and so on.
+
+ When the current loop changes, QAbstractAnimation emits the
+ currentLoopChanged() signal.
+*/
+int QAbstractAnimation::currentLoop() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->currentLoop;
+}
+
+/*!
+ \fn virtual int QAbstractAnimation::duration() const = 0
+
+ This pure virtual function returns the duration of the animation, and
+ defines for how long QAbstractAnimation should update the current
+ time. This duration is local, and does not include the loop count.
+
+ A return value of -1 indicates that the animation has no defined duration;
+ the animation should run forever until stopped. This is useful for
+ animations that are not time driven, or where you cannot easily predict
+ its duration (e.g., event driven audio playback in a game).
+
+ If the animation is a parallel QAnimationGroup, the duration will be the longest
+ duration of all its animations. If the animation is a sequential QAnimationGroup,
+ the duration will be the sum of the duration of all its animations.
+ \sa loopCount
+*/
+
+/*!
+ Returns the total and effective duration of the animation, including the
+ loop count.
+
+ \sa duration(), currentTime
+*/
+int QAbstractAnimation::totalDuration() const
+{
+ Q_D(const QAbstractAnimation);
+ if (d->loopCount < 0)
+ return -1;
+ int dura = duration();
+ if (dura == -1)
+ return -1;
+ return dura * d->loopCount;
+}
+
+/*!
+ \property QAbstractAnimation::currentTime
+ \brief the current time and progress of the animation
+
+ This property describes the animation's current time. You can change the
+ current time by calling setCurrentTime, or you can call start() and let
+ the animation run, setting the current time automatically as the animation
+ progresses.
+
+ The animation's current time starts at 0, and ends at duration(). If the
+ animation's loopCount is larger than 1, the current time will rewind and
+ start at 0 again for the consecutive loops. If the animation has a pause.
+ currentTime will also include the duration of the pause.
+
+ \sa loopCount
+ */
+int QAbstractAnimation::currentTime() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->currentTime;
+}
+void QAbstractAnimation::setCurrentTime(int msecs)
+{
+ Q_D(QAbstractAnimation);
+ msecs = qMax(msecs, 0);
+
+ // Calculate new time and loop.
+ int dura = duration();
+ int totalDura = (d->loopCount < 0 || dura == -1) ? -1 : dura * d->loopCount;
+ if (totalDura != -1)
+ msecs = qMin(totalDura, msecs);
+ d->totalCurrentTime = msecs;
+
+ // Update new values.
+ int oldLoop = d->currentLoop;
+ d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura));
+ if (d->currentLoop == d->loopCount) {
+ //we're at the end
+ d->currentTime = qMax(0, dura);
+ d->currentLoop = qMax(0, d->loopCount - 1);
+ } else {
+ if (d->direction == Forward) {
+ d->currentTime = (dura <= 0) ? msecs : (msecs % dura);
+ } else {
+ d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1;
+ if (d->currentTime == dura)
+ --d->currentLoop;
+ }
+ }
+
+ updateCurrentTime(msecs);
+ if (d->currentLoop != oldLoop)
+ emit currentLoopChanged(d->currentLoop);
+
+ // All animations are responsible for stopping the animation when their
+ // own end state is reached; in this case the animation is time driven,
+ // and has reached the end.
+ if ((d->direction == Forward && d->totalCurrentTime == totalDura)
+ || (d->direction == Backward && d->totalCurrentTime == 0)) {
+ stop();
+ }
+}
+
+/*!
+ Starts the animation. The \a policy argument says whether or not the
+ animation should be deleted when it's done. When the animation starts, the
+ stateChanged() signal is emitted, and state() returns Running. When control
+ reaches the event loop, the animation will run by itself, periodically
+ calling updateCurrentTime() as the animation progresses.
+
+ If the animation is currently stopped or has already reached the end,
+ calling start() will rewind the animation and start again from the beginning.
+ When the animation reaches the end, the animation will either stop, or
+ if the loop level is more than 1, it will rewind and continue from the beginning.
+
+ If the animation is already running, this function does nothing.
+
+ \sa stop(), state()
+*/
+void QAbstractAnimation::start(DeletionPolicy policy)
+{
+ Q_D(QAbstractAnimation);
+ if (d->state == Running)
+ return;
+ d->setState(Running);
+ d->deleteWhenStopped = policy;
+}
+
+/*!
+ Stops the animation. When the animation is stopped, it emits the stateChanged()
+ signal, and state() returns Stopped. The current time is not changed.
+
+ If the animation stops by itself after reaching the end (i.e.,
+ currentTime() == duration() and currentLoop() > loopCount() - 1), the
+ finished() signal is emitted.
+
+ \sa start(), state()
+ */
+void QAbstractAnimation::stop()
+{
+ Q_D(QAbstractAnimation);
+
+ d->setState(Stopped);
+}
+
+/*!
+ Pauses the animation. When the animation is paused, state() returns Paused.
+ The currenttime will remain unchanged until resume() or start() is called.
+ If you want to continue from the current time, call resume().
+
+
+ \sa start(), state(), resume()
+ */
+void QAbstractAnimation::pause()
+{
+ Q_D(QAbstractAnimation);
+ if (d->state == Stopped) {
+ qWarning("QAbstractAnimation::pause: Cannot pause a stopped animation");
+ return;
+ }
+
+ d->setState(Paused);
+}
+
+/*!
+ Resumes the animation after it was paused. When the animation is resumed,
+ it emits the resumed() and stateChanged() signals. The currenttime is not
+ changed.
+
+ \sa start(), pause(), state()
+ */
+void QAbstractAnimation::resume()
+{
+ Q_D(QAbstractAnimation);
+ if (d->state != Paused) {
+ qWarning("QAbstractAnimation::resume: "
+ "Cannot resume an animation that is not paused");
+ return;
+ }
+
+ d->setState(Running);
+}
+
+/*!
+ \reimp
+*/
+bool QAbstractAnimation::event(QEvent *event)
+{
+ return QObject::event(event);
+}
+
+/*!
+ \fn virtual void QAbstractAnimation::updateCurrentTime(int msecs) = 0;
+
+ This pure virtual function is called every time the animation's current
+ time changes. The \a msecs argument is the current time.
+
+ \sa updateState()
+*/
+
+/*!
+ This virtual function is called by QAbstractAnimation when the state
+ of the animation is changed from \a oldState to \a newState.
+
+ \sa start(), stop(), pause(), resume()
+*/
+void QAbstractAnimation::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_UNUSED(oldState);
+ Q_UNUSED(newState);
+}
+
+/*!
+ This virtual function is called by QAbstractAnimation when the direction
+ of the animation is changed. The \a direction argument is the new direction.
+
+ \sa setDirection(), direction()
+*/
+void QAbstractAnimation::updateDirection(QAbstractAnimation::Direction direction)
+{
+ Q_UNUSED(direction);
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qabstractanimation.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h
new file mode 100644
index 0000000..a7f0082
--- /dev/null
+++ b/src/corelib/animation/qabstractanimation.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTANIMATION_H
+#define QABSTRACTANIMATION_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QAnimationGroup;
+class QSequentialAnimationGroup;
+
+class QAbstractAnimationPrivate;
+class Q_CORE_EXPORT QAbstractAnimation : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(State state READ state NOTIFY stateChanged)
+ Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount)
+ Q_PROPERTY(int currentTime READ currentTime WRITE setCurrentTime)
+ Q_PROPERTY(int currentLoop READ currentLoop NOTIFY currentLoopChanged)
+ Q_PROPERTY(Direction direction READ direction WRITE setDirection NOTIFY directionChanged)
+ Q_PROPERTY(int duration READ duration)
+
+public:
+ enum Direction {
+ Forward,
+ Backward
+ };
+
+ enum State {
+ Stopped,
+ Paused,
+ Running
+ };
+
+ enum DeletionPolicy {
+ KeepWhenStopped = 0,
+ DeleteWhenStopped
+ };
+
+ QAbstractAnimation(QObject *parent = 0);
+ virtual ~QAbstractAnimation();
+
+ State state() const;
+
+ QAnimationGroup *group() const;
+
+ Direction direction() const;
+ void setDirection(Direction direction);
+
+ int loopCount() const;
+ void setLoopCount(int loopCount);
+ int currentLoop() const;
+
+ virtual int duration() const = 0;
+ int totalDuration() const;
+
+ int currentTime() const;
+
+Q_SIGNALS:
+ void finished();
+ void stateChanged(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ void currentLoopChanged(int currentLoop);
+ void directionChanged(QAbstractAnimation::Direction);
+
+public Q_SLOTS:
+ void start(QAbstractAnimation::DeletionPolicy policy = KeepWhenStopped);
+ void pause();
+ void resume();
+ void stop();
+ void setCurrentTime(int msecs);
+
+protected:
+ QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent = 0);
+ bool event(QEvent *event);
+
+ virtual void updateCurrentTime(int msecs) = 0;
+ virtual void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ virtual void updateDirection(QAbstractAnimation::Direction direction);
+
+#ifdef QT_EXPERIMENTAL_SOLUTION
+ QAbstractAnimationPrivate *d_ptr;
+#endif
+
+private:
+ Q_DISABLE_COPY(QAbstractAnimation)
+ Q_DECLARE_PRIVATE(QAbstractAnimation)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QABSTRACTANIMATION_H
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
new file mode 100644
index 0000000..41983a5
--- /dev/null
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTANIMATION_P_H
+#define QABSTRACTANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qbasictimer.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qtimer.h>
+#ifndef QT_EXPERIMENTAL_SOLUTION
+#include <private/qobject_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QAnimationGroup;
+class QAbstractAnimation;
+#ifdef QT_EXPERIMENTAL_SOLUTION
+class QAbstractAnimationPrivate
+#else
+class QAbstractAnimationPrivate : public QObjectPrivate
+#endif
+{
+public:
+ QAbstractAnimationPrivate()
+ : state(QAbstractAnimation::Stopped),
+ direction(QAbstractAnimation::Forward),
+ deleteWhenStopped(false),
+ totalCurrentTime(0),
+ currentTime(0),
+ loopCount(1),
+ currentLoop(0),
+ group(0)
+ {
+ }
+
+ virtual ~QAbstractAnimationPrivate() {}
+
+ static QAbstractAnimationPrivate *get(QAbstractAnimation *q)
+ {
+ return q->d_func();
+ }
+
+ QAbstractAnimation::State state;
+ QAbstractAnimation::Direction direction;
+ bool deleteWhenStopped;
+ void setState(QAbstractAnimation::State state);
+
+ int totalCurrentTime;
+ int currentTime;
+ int loopCount;
+ int currentLoop;
+
+ QAnimationGroup *group;
+#ifdef QT_EXPERIMENTAL_SOLUTION
+ QAbstractAnimation *q_ptr;
+#endif
+
+private:
+ Q_DECLARE_PUBLIC(QAbstractAnimation)
+};
+
+
+class Q_CORE_EXPORT QUnifiedTimer : public QObject
+{
+private:
+ QUnifiedTimer();
+
+public:
+ static QUnifiedTimer *instance();
+
+ void registerAnimation(QAbstractAnimation *animation);
+ void unregisterAnimation(QAbstractAnimation *animation);
+
+ void setTimingInterval(int interval);
+ void setConsistentTiming(bool consistent);
+
+ int elapsedTime() const;
+
+protected:
+ void timerEvent(QTimerEvent *);
+ void updateTimer();
+
+private:
+ void updateRecentlyStartedAnimations();
+
+ QBasicTimer animationTimer, startStopAnimationTimer;
+ QTime time;
+ int lastTick;
+ int timingInterval;
+ bool consistentTiming;
+ QList<QAbstractAnimation*> animations, animationsToStart;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp
new file mode 100644
index 0000000..8c9f358
--- /dev/null
+++ b/src/corelib/animation/qanimationgroup.cpp
@@ -0,0 +1,275 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QAnimationGroup
+ \brief The QAnimationGroup class is an abstract base class for group of animations.
+ \since 4.5
+ \ingroup group_animation
+ \preliminary
+
+ QAnimationGroup represents a group of animations, such as parallel or sequential,
+ and lets you combine different animations into one. The group manages any animation
+ that inherits QAbstractAnimation. By combining groups, you can easily construct
+ complex animation graphs.
+
+ The QAnimationGroup base class provides methods for adding and retrieving animations.
+ Besides that, you can remove animations by calling remove(), and clear the animation
+ group by calling clearAnimations(). You may keep track of changes in the group's animations by
+ listening to QEvent::ChildAdded and QEvent::ChildRemoved events.
+
+ QAnimationGroup takes ownership of the animations it manages, and ensures that they are
+ deleted when the animation group is deleted.
+
+ \sa QAbstractAnimation, QVariantAnimation, {The Animation Framework}
+*/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qanimationgroup.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qcoreevent.h>
+#include "qanimationgroup_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ Constructs a QAnimationGroup.
+ \a parent is passed to QObject's constructor.
+*/
+QAnimationGroup::QAnimationGroup(QObject *parent)
+ : QAbstractAnimation(*new QAnimationGroupPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QAnimationGroup::QAnimationGroup(QAnimationGroupPrivate &dd, QObject *parent)
+ : QAbstractAnimation(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation group. It will also destroy all its animations.
+*/
+QAnimationGroup::~QAnimationGroup()
+{
+}
+
+/*!
+ Returns a pointer to the animation at \a index in this group. This
+ function is useful when you need access to a particular animation. \a
+ index is between 0 and animationCount() - 1.
+
+ \sa animationCount(), indexOfAnimation()
+*/
+QAbstractAnimation *QAnimationGroup::animationAt(int index) const
+{
+ Q_D(const QAnimationGroup);
+
+ if (index < 0 || index >= d->animations.size()) {
+ qWarning("QAnimationGroup::animationAt: index is out of bounds");
+ return 0;
+ }
+
+ return d->animations.at(index);
+}
+
+
+/*!
+ Returns the number of animations managed by this group.
+
+ \sa indexOfAnimation(), addAnimation(), animationAt()
+*/
+int QAnimationGroup::animationCount() const
+{
+ Q_D(const QAnimationGroup);
+ return d->animations.size();
+}
+
+/*!
+ Returns the index of \a animation. The returned index can be passed
+ to the other functions that take an index as an argument.
+
+ \sa insertAnimationAt() animationAt(), takeAnimationAt()
+*/
+int QAnimationGroup::indexOfAnimation(QAbstractAnimation *animation) const
+{
+ Q_D(const QAnimationGroup);
+ return d->animations.indexOf(animation);
+}
+
+/*!
+ Adds \a animation to this group. This will call insertAnimationAt with
+ index equals to animationCount()
+*/
+void QAnimationGroup::addAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+ insertAnimationAt(d->animations.count(), animation);
+}
+
+/*!
+ Inserts \a animation into this animation group at \a index.
+ If \a index is 0 the animation is inserted at the beginning.
+ If \a index is animationCount(), the animation is inserted at the end.
+ \sa takeAnimationAt(), addAnimation(), indexOfAnimation()
+*/
+void QAnimationGroup::insertAnimationAt(int index, QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+
+ if (index < 0 || index > d->animations.size()) {
+ qWarning("QAnimationGroup::insertAnimationAt: index is out of bounds");
+ return;
+ }
+
+ if (QAnimationGroup *oldGroup = animation->group())
+ oldGroup->removeAnimation(animation);
+
+ d->animations.insert(index, animation);
+ QAbstractAnimationPrivate::get(animation)->group = this;
+ // this will make sure that ChildAdded event is sent to 'this'
+ animation->setParent(this);
+ d->animationInsertedAt(index);
+}
+
+/*!
+ Removes \a animation from this group. The ownership of \a animation is
+ transferred to the caller.
+
+ \sa takeAnimationAt(), insertAnimationAt(), addAnimation()
+*/
+void QAnimationGroup::removeAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+
+ if (!animation) {
+ qWarning("QAnimationGroup::remove: cannot remove null animation");
+ return;
+ }
+ int index = d->animations.indexOf(animation);
+ if (index == -1) {
+ qWarning("QAnimationGroup::remove: animation is not part of this group");
+ return;
+ }
+
+ takeAnimationAt(index);
+}
+
+/*!
+ Removes the animation at \a index from this animation group. The ownership
+ of the animation is transferred to the caller, and a pointer to the removed
+ animation is returned.
+
+ \sa addAnimation()
+*/
+QAbstractAnimation *QAnimationGroup::takeAnimationAt(int index)
+{
+ Q_D(QAnimationGroup);
+ if (index < 0 || index >= d->animations.size()) {
+ qWarning("QAnimationGroup::takeAnimationAt: no animation at index %d", index);
+ return 0;
+ }
+ QAbstractAnimation *animation = d->animations.at(index);
+ QAbstractAnimationPrivate::get(animation)->group = 0;
+ // ### removing from list before doing setParent to avoid inifinite recursion
+ // in ChildRemoved event
+ d->animations.removeAt(index);
+ animation->setParent(0);
+ d->animationRemovedAt(index);
+ return animation;
+}
+
+/*!
+ Removes and deletes all animations in this animation group, and resets the current
+ time to 0.
+
+ \sa addAnimation(), removeAnimation()
+*/
+void QAnimationGroup::clearAnimations()
+{
+ Q_D(QAnimationGroup);
+ qDeleteAll(d->animations);
+}
+
+/*!
+ \reimp
+*/
+bool QAnimationGroup::event(QEvent *event)
+{
+ Q_D(QAnimationGroup);
+ if (event->type() == QEvent::ChildAdded) {
+ QChildEvent *childEvent = static_cast<QChildEvent *>(event);
+ if (QAbstractAnimation *a = qobject_cast<QAbstractAnimation *>(childEvent->child())) {
+ if (a->group() != this)
+ addAnimation(a);
+ }
+ } else if (event->type() == QEvent::ChildRemoved) {
+ QChildEvent *childEvent = static_cast<QChildEvent *>(event);
+ QAbstractAnimation *a = static_cast<QAbstractAnimation *>(childEvent->child());
+ // You can only rely on the child being a QObject because in the QEvent::ChildRemoved
+ // case it might be called from the destructor.
+ int index = d->animations.indexOf(a);
+ if (index != -1)
+ takeAnimationAt(index);
+ }
+ return QAbstractAnimation::event(event);
+}
+
+
+void QAnimationGroupPrivate::animationRemovedAt(int index)
+{
+ Q_Q(QAnimationGroup);
+ Q_UNUSED(index);
+ if (animations.isEmpty()) {
+ currentTime = 0;
+ q->stop();
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qanimationgroup.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qanimationgroup.h b/src/corelib/animation/qanimationgroup.h
new file mode 100644
index 0000000..7dee070
--- /dev/null
+++ b/src/corelib/animation/qanimationgroup.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATIONGROUP_H
+#define QANIMATIONGROUP_H
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qabstractanimation.h"
+#else
+# include <QtCore/qabstractanimation.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QAnimationGroupPrivate;
+class Q_CORE_EXPORT QAnimationGroup : public QAbstractAnimation
+{
+ Q_OBJECT
+
+public:
+ QAnimationGroup(QObject *parent = 0);
+ ~QAnimationGroup();
+
+ QAbstractAnimation *animationAt(int index) const;
+ int animationCount() const;
+ int indexOfAnimation(QAbstractAnimation *animation) const;
+ void addAnimation(QAbstractAnimation *animation);
+ void insertAnimationAt(int index, QAbstractAnimation *animation);
+ void removeAnimation(QAbstractAnimation *animation);
+ QAbstractAnimation *takeAnimationAt(int index);
+ void clearAnimations();
+
+protected:
+ QAnimationGroup(QAnimationGroupPrivate &dd, QObject *parent);
+ bool event(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QAnimationGroup)
+ Q_DECLARE_PRIVATE(QAnimationGroup)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QANIMATIONGROUP_H
diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h
new file mode 100644
index 0000000..a7bd0fa
--- /dev/null
+++ b/src/corelib/animation/qanimationgroup_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATIONGROUP_P_H
+#define QANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qanimationgroup.h"
+
+#include <QtCore/qlist.h>
+
+#include "qabstractanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAnimationGroupPrivate : public QAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QAnimationGroup)
+public:
+ QAnimationGroupPrivate()
+ { }
+
+ virtual void animationInsertedAt(int index) { Q_UNUSED(index) };
+ virtual void animationRemovedAt(int index);
+
+ QList<QAbstractAnimation *> animations;
+};
+
+QT_END_NAMESPACE
+
+#endif //QANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp
new file mode 100644
index 0000000..a75f85c
--- /dev/null
+++ b/src/corelib/animation/qparallelanimationgroup.cpp
@@ -0,0 +1,298 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QParallelAnimationGroup
+ \brief The QParallelAnimationGroup class provides a parallel group of animations.
+ \since 4.5
+ \ingroup group_animation
+ \preliminary
+
+ The animations are all started at the same time, and run in parallel. The animation group
+ finishes when the longest lasting animation has finished.
+*/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qparallelanimationgroup.h"
+#include "qparallelanimationgroup_p.h"
+//#define QANIMATION_DEBUG
+QT_BEGIN_NAMESPACE
+
+/*!
+ Constructs a QParallelAnimationGroup.
+ \a parent is passed to QObject's constructor.
+*/
+QParallelAnimationGroup::QParallelAnimationGroup(QObject *parent)
+ : QAnimationGroup(*new QParallelAnimationGroupPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QParallelAnimationGroup::QParallelAnimationGroup(QParallelAnimationGroupPrivate &dd,
+ QObject *parent)
+ : QAnimationGroup(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation group. It will also destroy all its animations.
+*/
+QParallelAnimationGroup::~QParallelAnimationGroup()
+{
+}
+
+/*!
+ \reimp
+*/
+int QParallelAnimationGroup::duration() const
+{
+ Q_D(const QParallelAnimationGroup);
+ int ret = 0;
+
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ const int currentDuration = animation->totalDuration();
+ if (currentDuration == -1)
+ return -1; // Undetermined length
+
+ ret = qMax(ret, currentDuration);
+ }
+
+ return ret;
+}
+
+/*!
+ \reimp
+*/
+void QParallelAnimationGroup::updateCurrentTime(int)
+{
+ Q_D(QParallelAnimationGroup);
+ if (d->animations.isEmpty())
+ return;
+
+ if (d->currentLoop > d->lastLoop) {
+ // simulate completion of the loop
+ int dura = duration();
+ if (dura > 0) {
+ foreach (QAbstractAnimation *animation, d->animations) {
+ animation->setCurrentTime(dura); // will stop
+ }
+ }
+ } else if (d->currentLoop < d->lastLoop) {
+ // simulate completion of the loop seeking backwards
+ foreach (QAbstractAnimation *animation, d->animations) {
+ animation->setCurrentTime(0);
+ animation->stop();
+ }
+ }
+
+ bool timeFwd = ((d->currentLoop == d->lastLoop && d->currentTime >= d->lastCurrentTime)
+ || d->currentLoop > d->lastLoop);
+#ifdef QANIMATION_DEBUG
+ qDebug("QParallellAnimationGroup %5d: setCurrentTime(%d), loop:%d, last:%d, timeFwd:%d, lastcurrent:%d, %d",
+ __LINE__, d->currentTime, d->currentLoop, d->lastLoop, timeFwd, d->lastCurrentTime, state());
+#endif
+ // finally move into the actual time of the current loop
+ foreach (QAbstractAnimation *animation, d->animations) {
+ const int dura = animation->totalDuration();
+ if (dura == -1 && d->isUncontrolledAnimationFinished(animation))
+ continue;
+ if (dura == -1 || (d->currentTime <= dura && dura != 0)
+ || (dura == 0 && d->currentLoop != d->lastLoop)) {
+ switch (state()) {
+ case Running:
+ animation->start();
+ break;
+ case Paused:
+ animation->pause();
+ break;
+ case Stopped:
+ default:
+ break;
+ }
+ }
+
+ if (dura <= 0) {
+ if (dura == -1)
+ animation->setCurrentTime(d->currentTime);
+ continue;
+ }
+
+ if ((timeFwd && d->lastCurrentTime <= dura)
+ || (!timeFwd && d->currentTime <= dura))
+ animation->setCurrentTime(d->currentTime);
+ if (d->currentTime > dura)
+ animation->stop();
+ }
+ d->lastLoop = d->currentLoop;
+ d->lastCurrentTime = d->currentTime;
+}
+
+/*!
+ \reimp
+*/
+void QParallelAnimationGroup::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_D(QParallelAnimationGroup);
+ QAnimationGroup::updateState(oldState, newState);
+
+ switch (newState) {
+ case Stopped:
+ foreach (QAbstractAnimation *animation, d->animations)
+ animation->stop();
+ d->disconnectUncontrolledAnimations();
+ break;
+ case Paused:
+ foreach (QAbstractAnimation *animation, d->animations)
+ animation->pause();
+ break;
+ case Running:
+ d->connectUncontrolledAnimations();
+ foreach (QAbstractAnimation *animation, d->animations) {
+ animation->stop();
+ animation->setDirection(d->direction);
+ animation->start();
+ }
+ break;
+ }
+}
+
+void QParallelAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
+{
+ Q_Q(QParallelAnimationGroup);
+
+ QAbstractAnimation *animation = qobject_cast<QAbstractAnimation *>(q->sender());
+ Q_ASSERT(animation);
+
+ int uncontrolledRunningCount = 0;
+ if (animation->duration() == -1 || animation->loopCount() < 0) {
+ QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin();
+ while (it != uncontrolledFinishTime.end()) {
+ if (it.key() == animation) {
+ *it = animation->currentTime();
+ }
+ if (it.value() == -1)
+ ++uncontrolledRunningCount;
+ ++it;
+ }
+ }
+
+ if (uncontrolledRunningCount > 0)
+ return;
+
+ int maxDuration = 0;
+ foreach (QAbstractAnimation *a, animations)
+ maxDuration = qMax(maxDuration, a->totalDuration());
+
+ if (currentTime >= maxDuration)
+ q->stop();
+}
+
+void QParallelAnimationGroupPrivate::disconnectUncontrolledAnimations()
+{
+ Q_Q(QParallelAnimationGroup);
+
+ QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin();
+ while (it != uncontrolledFinishTime.end()) {
+ QObject::disconnect(it.key(), SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
+ ++it;
+ }
+
+ uncontrolledFinishTime.clear();
+}
+
+void QParallelAnimationGroupPrivate::connectUncontrolledAnimations()
+{
+ Q_Q(QParallelAnimationGroup);
+
+ foreach (QAbstractAnimation *animation, animations) {
+ if (animation->duration() == -1 || animation->loopCount() < 0) {
+ uncontrolledFinishTime[animation] = -1;
+ QObject::connect(animation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
+ }
+ }
+}
+
+bool QParallelAnimationGroupPrivate::isUncontrolledAnimationFinished(QAbstractAnimation *anim) const
+{
+ return uncontrolledFinishTime.value(anim, -1) >= 0;
+}
+
+/*!
+ \reimp
+*/
+void QParallelAnimationGroup::updateDirection(QAbstractAnimation::Direction direction)
+{
+ Q_D(QParallelAnimationGroup);
+ //we need to update the direction of the current animation
+ if (state() != Stopped) {
+ foreach(QAbstractAnimation *anim, d->animations) {
+ anim->setDirection(direction);
+ }
+ } else {
+ if (direction == Forward) {
+ d->lastLoop = 0;
+ d->lastCurrentTime = 0;
+ } else {
+ // Looping backwards with loopCount == -1 does not really work well...
+ d->lastLoop = (d->loopCount == -1 ? 0 : d->loopCount - 1);
+ d->lastCurrentTime = duration();
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+bool QParallelAnimationGroup::event(QEvent *event)
+{
+ return QAnimationGroup::event(event);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qparallelanimationgroup.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qparallelanimationgroup.h b/src/corelib/animation/qparallelanimationgroup.h
new file mode 100644
index 0000000..48d66a3
--- /dev/null
+++ b/src/corelib/animation/qparallelanimationgroup.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPARALLELANIMATIONGROUP_H
+#define QPARALLELANIMATIONGROUP_H
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qanimationgroup.h"
+#else
+# include <QtCore/qanimationgroup.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QParallelAnimationGroupPrivate;
+class Q_CORE_EXPORT QParallelAnimationGroup : public QAnimationGroup
+{
+ Q_OBJECT
+
+public:
+ QParallelAnimationGroup(QObject *parent = 0);
+ ~QParallelAnimationGroup();
+
+ int duration() const;
+
+protected:
+ QParallelAnimationGroup(QParallelAnimationGroupPrivate &dd, QObject *parent);
+ bool event(QEvent *event);
+
+ void updateCurrentTime(int msecs);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ void updateDirection(QAbstractAnimation::Direction direction);
+
+private:
+ Q_DISABLE_COPY(QParallelAnimationGroup)
+ Q_DECLARE_PRIVATE(QParallelAnimationGroup)
+ Q_PRIVATE_SLOT(d_func(), void _q_uncontrolledAnimationFinished())
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPARALLELANIMATIONGROUP
diff --git a/src/corelib/animation/qparallelanimationgroup_p.h b/src/corelib/animation/qparallelanimationgroup_p.h
new file mode 100644
index 0000000..f36d972
--- /dev/null
+++ b/src/corelib/animation/qparallelanimationgroup_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPARALLELANIMATIONGROUP_P_H
+#define QPARALLELANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qparallelanimationgroup.h"
+#include "qanimationgroup_p.h"
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QParallelAnimationGroupPrivate : public QAnimationGroupPrivate
+{
+ Q_DECLARE_PUBLIC(QParallelAnimationGroup)
+public:
+ QParallelAnimationGroupPrivate()
+ : lastLoop(0), lastCurrentTime(0)
+ {
+ }
+
+ QHash<QAbstractAnimation*, int> uncontrolledFinishTime;
+ int lastLoop;
+ int lastCurrentTime;
+
+ bool isUncontrolledAnimationFinished(QAbstractAnimation *anim) const;
+ void connectUncontrolledAnimations();
+ void disconnectUncontrolledAnimations();
+
+ // private slot
+ void _q_uncontrolledAnimationFinished();
+};
+
+QT_END_NAMESPACE
+
+#endif //QPARALLELANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qpauseanimation.cpp b/src/corelib/animation/qpauseanimation.cpp
new file mode 100644
index 0000000..86c3049
--- /dev/null
+++ b/src/corelib/animation/qpauseanimation.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPauseAnimation
+ \brief The QPauseAnimation class provides a pause for QSequentialAnimationGroup.
+ \since 4.5
+ \ingroup group_animation
+ \preliminary
+*/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qpauseanimation.h"
+#include "qabstractanimation_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+class QPauseAnimationPrivate : public QAbstractAnimationPrivate
+{
+public:
+ QPauseAnimationPrivate() : QAbstractAnimationPrivate(), duration(0)
+ {
+ }
+
+ int duration;
+};
+
+/*!
+ Constructs a QPauseAnimation.
+ \a parent is passed to QObject's constructor.
+ The default duration is 0.
+*/
+
+QPauseAnimation::QPauseAnimation(QObject *parent) : QAbstractAnimation(*new QPauseAnimationPrivate, parent)
+{
+}
+
+/*!
+ Constructs a QPauseAnimation.
+ \a msecs is the duration of the pause.
+ \a parent is passed to QObject's constructor.
+*/
+
+QPauseAnimation::QPauseAnimation(int msecs, QObject *parent) : QAbstractAnimation(*new QPauseAnimationPrivate, parent)
+{
+ setDuration(msecs);
+}
+
+/*!
+ Destroys the pause animation.
+*/
+QPauseAnimation::~QPauseAnimation()
+{
+}
+
+/*!
+ \property QPauseAnimation::duration
+ \brief the duration of the pause.
+
+ The duration of the pause. The duration should not be negative.
+*/
+int QPauseAnimation::duration() const
+{
+ Q_D(const QPauseAnimation);
+ return d->duration;
+}
+
+void QPauseAnimation::setDuration(int msecs)
+{
+ if (msecs < 0) {
+ qWarning("QPauseAnimation::setDuration: cannot set a negative duration");
+ return;
+ }
+ Q_D(QPauseAnimation);
+ d->duration = msecs;
+}
+
+/*!
+ \reimp
+ */
+bool QPauseAnimation::event(QEvent *e)
+{
+ return QAbstractAnimation::event(e);
+}
+
+/*!
+ \reimp
+ */
+void QPauseAnimation::updateCurrentTime(int msecs)
+{
+ Q_UNUSED(msecs);
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qpauseanimation.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qpauseanimation.h b/src/corelib/animation/qpauseanimation.h
new file mode 100644
index 0000000..595f2d0
--- /dev/null
+++ b/src/corelib/animation/qpauseanimation.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPAUSEANIMATION_P_H
+#define QPAUSEANIMATION_P_H
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qanimationgroup.h"
+#else
+# include <QtCore/qanimationgroup.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QPauseAnimationPrivate;
+
+class Q_CORE_EXPORT QPauseAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(int duration READ duration WRITE setDuration)
+public:
+ QPauseAnimation(QObject *parent = 0);
+ QPauseAnimation(int msecs, QObject *parent = 0);
+ ~QPauseAnimation();
+
+ int duration() const;
+ void setDuration(int msecs);
+
+protected:
+ bool event(QEvent *e);
+ void updateCurrentTime(int msecs);
+
+private:
+ Q_DISABLE_COPY(QPauseAnimation)
+ Q_DECLARE_PRIVATE(QPauseAnimation)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPAUSEANIMATION_P_H
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp
new file mode 100644
index 0000000..96cfa6b
--- /dev/null
+++ b/src/corelib/animation/qpropertyanimation.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPropertyAnimation
+ \brief The QPropertyAnimation class animates Qt properties
+ \ingroup animation
+ \preliminary
+
+ QPropertyAnimation interpolates over \l{Qt's Property System}{Qt
+ properties}. As property values are stored in \l{QVariant}s, the
+ class inherits QVariantAnimation, and supports animation of the
+ same \l{QVariant::Type}{variant types} as its super class.
+
+ A class declaring properties must be a QObject. To make it
+ possible to animate a property, it must provide a setter (so that
+ QPropertyAnimation can set the property's value). Note that this
+ makes it possible to animate many of Qt's widgets. Let's look at
+ an example:
+
+ \code
+ QPropertyAnimation animation(myWidget, "geometry");
+ animation.setDuration(10000);
+ animation.setStartValue(QRect(0, 0, 100, 30));
+ animation.setEndValue(QRect(250, 250, 100, 30));
+
+ animation.start();
+ \endcode
+
+ The property name and the QObject instance of which property
+ should be animated are passed to the constructor. You can then
+ specify the start and end value of the property. The procedure is
+ equal for properties in classes you have implemented
+ yourself--just check with QVariantAnimation that your QVariant
+ type is supported.
+
+ The QVariantAnimation class description explains how to set up the
+ animation in detail. Note, however, that if a start value is not
+ set, the property will start at the value it had when the
+ QPropertyAnimation instance was created.
+
+ QPropertyAnimation works like a charm on its own. For complex
+ animations that, for instance, contain several objects,
+ QAnimationGroup is provided. An animation group is an animation
+ that can contain other animations, and that can manage when its
+ animations are played. Look at QParallelAnimationGroup for an
+ example.
+
+ \sa QVariantAnimation, QAnimationGroup, {The Animation Framework}
+*/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qpropertyanimation.h"
+#include "qanimationgroup.h"
+#include <QtCore/qdebug.h>
+
+#include "qpropertyanimation_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+typedef QPair<QObject *, QByteArray> QPropertyAnimationPair;
+typedef QHash<QPropertyAnimationPair, QPropertyAnimation*> QPropertyAnimationHash;
+Q_GLOBAL_STATIC(QPropertyAnimationHash, _q_runningAnimations);
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, guardHashLock, (QMutex::Recursive) )
+
+void QPropertyAnimationPrivate::updateMetaProperty()
+{
+ if (!target || propertyName.isEmpty())
+ return;
+
+ if (hasMetaProperty == 0 && !property.isValid()) {
+ const QMetaObject *mo = target->metaObject();
+ propertyIndex = mo->indexOfProperty(propertyName);
+ if (propertyIndex != -1) {
+ hasMetaProperty = 1;
+ property = mo->property(propertyIndex);
+ propertyType = property.userType();
+ } else {
+ if (!target->dynamicPropertyNames().contains(propertyName))
+ qWarning("QPropertyAnimation: you're trying to animate a non-existing property %s of your QObject", propertyName.constData());
+ hasMetaProperty = 2;
+ }
+ }
+
+ if (property.isValid())
+ convertValues(propertyType);
+}
+
+void QPropertyAnimationPrivate::updateProperty(const QVariant &newValue)
+{
+ if (!target || state == QAbstractAnimation::Stopped)
+ return;
+
+ if (hasMetaProperty == 1) {
+ if (newValue.userType() == propertyType) {
+ //no conversion is needed, we directly call the QObject::qt_metacall
+ void *data = const_cast<void*>(newValue.constData());
+ target->qt_metacall(QMetaObject::WriteProperty, propertyIndex, &data);
+ } else {
+ property.write(target, newValue);
+ }
+ } else {
+ target->setProperty(propertyName.constData(), newValue);
+ }
+}
+
+/*!
+ Construct a QPropertyAnimation object. \a parent is passed to QObject's
+ constructor.
+*/
+QPropertyAnimation::QPropertyAnimation(QObject *parent)
+ : QVariantAnimation(*new QPropertyAnimationPrivate, parent)
+{
+}
+
+/*!
+ Construct a QPropertyAnimation object. \a parent is passed to QObject's
+ constructor. The animation changes the property \a propertyName on \a
+ target. The default duration is 250ms.
+
+ \sa targetObject, propertyName
+*/
+QPropertyAnimation::QPropertyAnimation(QObject *target, const QByteArray &propertyName, QObject *parent)
+ : QVariantAnimation(*new QPropertyAnimationPrivate, parent)
+{
+ setTargetObject(target);
+ setPropertyName(propertyName);
+}
+
+/*!
+ Destroys the QPropertyAnimation instance.
+ */
+QPropertyAnimation::~QPropertyAnimation()
+{
+ stop();
+}
+
+/*!
+ \property QPropertyAnimation::targetObject
+ \brief the target QObject for this animation.
+
+ This property defines the target QObject for this animation.
+ */
+QObject *QPropertyAnimation::targetObject() const
+{
+ Q_D(const QPropertyAnimation);
+ return d->target;
+}
+void QPropertyAnimation::setTargetObject(QObject *target)
+{
+ Q_D(QPropertyAnimation);
+ if (d->target == target)
+ return;
+
+ d->target = target;
+ d->hasMetaProperty = 0;
+ d->updateMetaProperty();
+}
+
+/*!
+ \property QPropertyAnimation::propertyName
+ \brief the target property name for this animation
+
+ This property defines the target property name for this animation. The
+ property name is required for the animation to operate.
+ */
+QByteArray QPropertyAnimation::propertyName() const
+{
+ Q_D(const QPropertyAnimation);
+ return d->propertyName;
+}
+void QPropertyAnimation::setPropertyName(const QByteArray &propertyName)
+{
+ Q_D(QPropertyAnimation);
+ d->propertyName = propertyName;
+ d->hasMetaProperty = 0;
+ d->updateMetaProperty();
+}
+
+
+/*!
+ \reimp
+ */
+bool QPropertyAnimation::event(QEvent *event)
+{
+ return QVariantAnimation::event(event);
+}
+
+/*!
+ This virtual function is called by QVariantAnimation whenever the current value
+ changes. \a value is the new, updated value. It updates the current value
+ of the property on the target object.
+
+ \sa currentValue, currentTime
+ */
+void QPropertyAnimation::updateCurrentValue(const QVariant &value)
+{
+ Q_D(QPropertyAnimation);
+ d->updateProperty(value);
+}
+
+/*!
+ \reimp
+
+ If the startValue is not defined when the state of the animation changes from Stopped to Running,
+ the current property value is used as the initial value for the animation.
+*/
+void QPropertyAnimation::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_D(QPropertyAnimation);
+
+ if (!d->target) {
+ qWarning("QPropertyAnimation::updateState: Changing state of an animation without target");
+ return;
+ }
+
+ QVariantAnimation::updateState(oldState, newState);
+ QMutexLocker locker(guardHashLock());
+ QPropertyAnimationHash * hash = _q_runningAnimations();
+ QPropertyAnimationPair key(d->target, d->propertyName);
+ if (newState == Running) {
+ d->updateMetaProperty();
+ QPropertyAnimation *oldAnim = hash->value(key, 0);
+ if (oldAnim) {
+ // try to stop the top level group
+ QAbstractAnimation *current = oldAnim;
+ while (current->group() && current->state() != Stopped)
+ current = current->group();
+ current->stop();
+ }
+ hash->insert(key, this);
+
+ // update the default start value
+ if (oldState == Stopped) {
+ d->setDefaultStartValue(d->target->property(d->propertyName.constData()));
+ }
+ } else if (hash->value(key) == this) {
+ hash->remove(key);
+ }
+}
+
+#include "moc_qpropertyanimation.cpp"
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qpropertyanimation.h b/src/corelib/animation/qpropertyanimation.h
new file mode 100644
index 0000000..b619256
--- /dev/null
+++ b/src/corelib/animation/qpropertyanimation.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROPERTYANIMATION_H
+#define QPROPERTYANIMATION_H
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qvariantanimation.h"
+#else
+# include <QtCore/qvariantanimation.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QPropertyAnimationPrivate;
+class Q_CORE_EXPORT QPropertyAnimation : public QVariantAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(QByteArray propertyName READ propertyName WRITE setPropertyName)
+ Q_PROPERTY(QObject* targetObject READ targetObject WRITE setTargetObject)
+
+public:
+ QPropertyAnimation(QObject *parent = 0);
+ QPropertyAnimation(QObject *target, const QByteArray &propertyName, QObject *parent = 0);
+ ~QPropertyAnimation();
+
+ QObject *targetObject() const;
+ void setTargetObject(QObject *target);
+
+ QByteArray propertyName() const;
+ void setPropertyName(const QByteArray &propertyName);
+
+protected:
+ bool event(QEvent *event);
+
+ void updateCurrentValue(const QVariant &value);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+private:
+ Q_DISABLE_COPY(QPropertyAnimation)
+ Q_DECLARE_PRIVATE(QPropertyAnimation)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPROPERTYANIMATION_H
diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h
new file mode 100644
index 0000000..ed3666d
--- /dev/null
+++ b/src/corelib/animation/qpropertyanimation_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROPERTYANIMATION_P_H
+#define QPROPERTYANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qpropertyanimation.h"
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qpointer.h>
+
+#include "qvariantanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPropertyAnimationPrivate : public QVariantAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QPropertyAnimation)
+public:
+ QPropertyAnimationPrivate()
+ : target(0), propertyType(0), propertyIndex(0), hasMetaProperty(false)
+ {
+ }
+
+
+ QPointer<QObject> target;
+
+ //for the QProperty
+ QMetaProperty property;
+ int propertyType;
+ int propertyIndex;
+
+ int hasMetaProperty;
+ QByteArray propertyName;
+ void updateProperty(const QVariant &);
+ void updateMetaProperty();
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp
new file mode 100644
index 0000000..45673c2
--- /dev/null
+++ b/src/corelib/animation/qsequentialanimationgroup.cpp
@@ -0,0 +1,572 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QSequentialAnimationGroup
+ \brief The QSequentialAnimationGroup class provides a sequential group of animations.
+ \since 4.5
+ \ingroup group_animation
+ \preliminary
+
+ The first animation in the group is started first, and when it finishes, the next animation
+ is started, and so on. The animation group finishes when the last animation has finished.
+
+ At each moment there is at most one animation that is active in the group, called currentAnimation.
+ An empty group has no current animation.
+
+ You can call addPause() or insertPause() to add a pause to a sequential animation group.
+*/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qsequentialanimationgroup.h"
+#include "qsequentialanimationgroup_p.h"
+
+#include "qpauseanimation.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+bool QSequentialAnimationGroupPrivate::atEnd() const
+{
+ // we try to detect if we're at the end of the group
+ //this is true if the following conditions are true:
+ // 1. we're in the last loop
+ // 2. the direction is forward
+ // 3. the current animation is the last one
+ // 4. the current animation has reached its end
+ const int animTotalCurrentTime = QAbstractAnimationPrivate::get(currentAnimation)->totalCurrentTime;
+ return (currentLoop == loopCount - 1
+ && direction == QAbstractAnimation::Forward
+ && currentAnimation == animations.last()
+ && animTotalCurrentTime == animationActualTotalDuration(currentAnimationIndex));
+}
+
+int QSequentialAnimationGroupPrivate::animationActualTotalDuration(int index) const
+{
+ QAbstractAnimation *anim = animations.at(index);
+ int ret = anim->totalDuration();
+ if (ret == -1 && actualDuration.size() > index)
+ ret = actualDuration.at(index); //we can try the actual duration there
+ return ret;
+}
+
+QSequentialAnimationGroupPrivate::AnimationIndex QSequentialAnimationGroupPrivate::indexForTime(int msecs) const
+{
+ Q_Q(const QSequentialAnimationGroup);
+ Q_ASSERT(!animations.isEmpty());
+
+ AnimationIndex ret;
+ int duration = 0;
+
+ // in case duration is -1, currentLoop will always be 0
+ ret.timeOffset = currentLoop * q->duration();
+
+ for (int i = 0; i < animations.size(); ++i) {
+ duration = animationActualTotalDuration(i);
+
+ // 'animation' is the current animation if one of these reasons is true:
+ // 1. it's duration is undefined
+ // 2. it ends after msecs
+ // 3. it is the last animation (this can happen in case there is at least 1 uncontrolled animation)
+ // 4. it ends exactly in msecs and the direction is backwards
+ if (duration == -1 || msecs < (ret.timeOffset + duration)
+ || (msecs == (ret.timeOffset + duration) && direction == QAbstractAnimation::Backward)) {
+ ret.index = i;
+ return ret;
+ }
+
+ // 'animation' has a non-null defined duration and is not the one at time 'msecs'.
+ ret.timeOffset += duration;
+ }
+
+ // this can only happen when one of those conditions is true:
+ // 1. the duration of the group is undefined and we passed its actual duration
+ // 2. there are only 0-duration animations in the group
+ ret.timeOffset -= duration;
+ ret.index = animations.size() - 1;
+ return ret;
+}
+
+void QSequentialAnimationGroupPrivate::restart()
+{
+ // restarting the group by making the first/last animation the current one
+ if (direction == QAbstractAnimation::Forward) {
+ lastLoop = 0;
+ if (currentAnimationIndex == 0)
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(0);
+ } else { // direction == QAbstractAnimation::Backward
+ lastLoop = loopCount - 1;
+ int index = animations.size() - 1;
+ if (currentAnimationIndex == index)
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(index);
+ }
+}
+
+/*!
+ \internal
+ This manages advancing the execution of a group running forwards (time has gone forward),
+ which is the same behaviour for rewinding the execution of a group running backwards
+ (time has gone backward).
+*/
+void QSequentialAnimationGroupPrivate::advanceForwards(const AnimationIndex &newAnimationIndex)
+{
+ if (lastLoop < currentLoop) {
+ // we need to fast forward to the end
+ for (int i = currentAnimationIndex; i < animations.size(); ++i) {
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(animationActualTotalDuration(i));
+ }
+ // this will make sure the current animation is reset to the beginning
+ if (animations.size() == 1)
+ // we need to force activation because setCurrentAnimation will have no effect
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(0, true);
+ }
+
+ // and now we need to fast forward from the current position to
+ for (int i = currentAnimationIndex; i < newAnimationIndex.index; ++i) { //### WRONG,
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(animationActualTotalDuration(i));
+ }
+ // setting the new current animation will happen later
+}
+
+/*!
+ \internal
+ This manages rewinding the execution of a group running forwards (time has gone forward),
+ which is the same behaviour for advancing the execution of a group running backwards
+ (time has gone backward).
+*/
+void QSequentialAnimationGroupPrivate::rewindForwards(const AnimationIndex &newAnimationIndex)
+{
+ if (lastLoop > currentLoop) {
+ // we need to fast rewind to the beginning
+ for (int i = currentAnimationIndex; i >= 0 ; --i) {
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(0);
+ }
+ // this will make sure the current animation is reset to the end
+ if (animations.size() == 1)
+ // we need to force activation because setCurrentAnimation will have no effect
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(animations.count() - 1, true);
+ }
+
+ // and now we need to fast rewind from the current position to
+ for (int i = currentAnimationIndex; i > newAnimationIndex.index; --i) {
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(0);
+ }
+ // setting the new current animation will happen later
+}
+
+/*!
+ \fn QSequentialAnimationGroup::currentAnimationChanged(QAbstractAnimation *current)
+
+ QSequentialAnimationGroup emits this signal when currentAnimation
+ has been changed. \a current is the current animation.
+
+ \sa currentAnimation()
+*/
+
+
+/*!
+ Constructs a QSequentialAnimationGroup.
+ \a parent is passed to QObject's constructor.
+*/
+QSequentialAnimationGroup::QSequentialAnimationGroup(QObject *parent)
+ : QAnimationGroup(*new QSequentialAnimationGroupPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QSequentialAnimationGroup::QSequentialAnimationGroup(QSequentialAnimationGroupPrivate &dd,
+ QObject *parent)
+ : QAnimationGroup(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation group. It will also destroy all its animations.
+*/
+QSequentialAnimationGroup::~QSequentialAnimationGroup()
+{
+}
+
+/*!
+ Adds a pause of \a msecs to this animation group.
+ The pause is considered as a special type of animation, thus count() will be
+ increased by one.
+ \sa insertPauseAt(), QAnimationGroup::addAnimation()
+*/
+QPauseAnimation *QSequentialAnimationGroup::addPause(int msecs)
+{
+ QPauseAnimation *pause = new QPauseAnimation(msecs);
+ addAnimation(pause);
+ return pause;
+}
+
+/*!
+ Inserts a pause of \a msecs milliseconds at \a index in this animation
+ group.
+
+ \sa addPause(), QAnimationGroup::insertAnimationAt()
+*/
+QPauseAnimation *QSequentialAnimationGroup::insertPauseAt(int index, int msecs)
+{
+ Q_D(const QSequentialAnimationGroup);
+
+ if (index < 0 || index > d->animations.size()) {
+ qWarning("QSequentialAnimationGroup::insertPauseAt: index is out of bounds");
+ return 0;
+ }
+
+ QPauseAnimation *pause = new QPauseAnimation(msecs);
+ insertAnimationAt(index, pause);
+ return pause;
+}
+
+
+/*!
+ \property QSequentialAnimationGroup::currentAnimation
+ Returns the animation in the current time.
+
+ \sa currentAnimationChanged()
+*/
+QAbstractAnimation *QSequentialAnimationGroup::currentAnimation() const
+{
+ Q_D(const QSequentialAnimationGroup);
+ return d->currentAnimation;
+}
+
+/*!
+ \reimp
+*/
+int QSequentialAnimationGroup::duration() const
+{
+ Q_D(const QSequentialAnimationGroup);
+ int ret = 0;
+
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ const int currentDuration = animation->totalDuration();
+ if (currentDuration == -1)
+ return -1; // Undetermined length
+
+ ret += currentDuration;
+ }
+
+ return ret;
+}
+
+/*!
+ \reimp
+*/
+void QSequentialAnimationGroup::updateCurrentTime(int msecs)
+{
+ Q_D(QSequentialAnimationGroup);
+ if (!d->currentAnimation)
+ return;
+
+ const QSequentialAnimationGroupPrivate::AnimationIndex newAnimationIndex = d->indexForTime(msecs);
+
+ // remove unneeded animations from actualDuration list
+ while (newAnimationIndex.index < d->actualDuration.size())
+ d->actualDuration.removeLast();
+
+ // newAnimationIndex.index is the new current animation
+ if (d->lastLoop < d->currentLoop
+ || (d->lastLoop == d->currentLoop && d->currentAnimationIndex < newAnimationIndex.index)) {
+ // advancing with forward direction is the same as rewinding with backwards direction
+ d->advanceForwards(newAnimationIndex);
+ } else if (d->lastLoop > d->currentLoop
+ || (d->lastLoop == d->currentLoop && d->currentAnimationIndex > newAnimationIndex.index)) {
+ // rewinding with forward direction is the same as advancing with backwards direction
+ d->rewindForwards(newAnimationIndex);
+ }
+
+ d->setCurrentAnimation(newAnimationIndex.index);
+
+ const int newCurrentTime = msecs - newAnimationIndex.timeOffset;
+
+ if (d->currentAnimation) {
+ d->currentAnimation->setCurrentTime(newCurrentTime);
+ if (d->atEnd()) {
+ //we make sure that we don't exceed the duration here
+ d->currentTime += QAbstractAnimationPrivate::get(d->currentAnimation)->totalCurrentTime - newCurrentTime;
+ stop();
+ }
+ } else {
+ //the only case where currentAnimation could be null
+ //is when all animations have been removed
+ Q_ASSERT(d->animations.isEmpty());
+ d->currentTime = 0;
+ stop();
+ }
+
+ d->lastLoop = d->currentLoop;
+}
+
+/*!
+ \reimp
+*/
+void QSequentialAnimationGroup::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_D(QSequentialAnimationGroup);
+ QAnimationGroup::updateState(oldState, newState);
+
+ if (!d->currentAnimation)
+ return;
+
+ switch (newState) {
+ case Stopped:
+ d->currentAnimation->stop();
+ break;
+ case Paused:
+ if (oldState == d->currentAnimation->state()
+ && oldState == QSequentialAnimationGroup::Running) {
+ d->currentAnimation->pause();
+ }
+ else
+ d->restart();
+ break;
+ case Running:
+ if (oldState == d->currentAnimation->state()
+ && oldState == QSequentialAnimationGroup::Paused)
+ d->currentAnimation->start();
+ else
+ d->restart();
+ break;
+ }
+}
+
+/*!
+ \reimp
+*/
+void QSequentialAnimationGroup::updateDirection(QAbstractAnimation::Direction direction)
+{
+ Q_D(QSequentialAnimationGroup);
+ // we need to update the direction of the current animation
+ if (state() != Stopped && d->currentAnimation)
+ d->currentAnimation->setDirection(direction);
+}
+
+/*!
+ \reimp
+*/
+bool QSequentialAnimationGroup::event(QEvent *event)
+{
+ return QAnimationGroup::event(event);
+}
+
+void QSequentialAnimationGroupPrivate::setCurrentAnimation(int index, bool intermediate)
+{
+ Q_Q(QSequentialAnimationGroup);
+
+ index = qMin(index, animations.count() - 1);
+
+ if (index == -1) {
+ Q_ASSERT(animations.isEmpty());
+ currentAnimationIndex = -1;
+ currentAnimation = 0;
+ return;
+ }
+
+ // need these two checks below because this func can be called after the current animation
+ // has been removed
+ if (index == currentAnimationIndex && animations.at(index) == currentAnimation)
+ return;
+
+ // stop the old current animation
+ if (currentAnimation)
+ currentAnimation->stop();
+
+ currentAnimation = animations.at(index);
+ currentAnimationIndex = index;
+
+ emit q->currentAnimationChanged(currentAnimation);
+
+ activateCurrentAnimation(intermediate);
+}
+
+void QSequentialAnimationGroupPrivate::activateCurrentAnimation(bool intermediate)
+{
+ Q_Q(QSequentialAnimationGroup);
+
+ if (!currentAnimation)
+ return;
+
+ if (state == QSequentialAnimationGroup::Stopped)
+ return;
+
+ currentAnimation->stop();
+
+ // we ensure the direction is consistent with the group's direction
+ currentAnimation->setDirection(direction);
+
+ // connects to the finish signal of uncontrolled animations
+ if (currentAnimation->totalDuration() == -1)
+ QObject::connect(currentAnimation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
+
+ currentAnimation->start();
+ if (!intermediate && state == QSequentialAnimationGroup::Paused)
+ currentAnimation->pause();
+}
+
+void QSequentialAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
+{
+ Q_Q(QSequentialAnimationGroup);
+ Q_ASSERT(qobject_cast<QAbstractAnimation *>(q->sender()) == currentAnimation);
+
+ // we trust the duration returned by the animation
+ while (actualDuration.size() < (currentAnimationIndex + 1))
+ actualDuration.append(-1);
+ actualDuration[currentAnimationIndex] = currentAnimation->currentTime();
+
+ QObject::disconnect(currentAnimation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
+
+ if ((direction == QAbstractAnimation::Forward && currentAnimation == animations.last())
+ || (direction == QAbstractAnimation::Backward && currentAnimationIndex == 0)) {
+ // we don't handle looping of a group with undefined duration
+ q->stop();
+ } else if (direction == QAbstractAnimation::Forward) {
+ // set the current animation to be the next one
+ setCurrentAnimation(currentAnimationIndex + 1);
+ } else {
+ // set the current animation to be the previous one
+ setCurrentAnimation(currentAnimationIndex - 1);
+ }
+}
+
+/*!
+ \internal
+ This method is called whenever an animation is added to
+ the group at index \a index.
+ Note: We only support insertion after the current animation
+*/
+void QSequentialAnimationGroupPrivate::animationInsertedAt(int index)
+{
+ if (currentAnimation == 0)
+ setCurrentAnimation(0); // initialize the current animation
+
+ if (currentAnimationIndex == index
+ && currentAnimation->currentTime() == 0 && currentAnimation->currentLoop() == 0) {
+ //in this case we simply insert an animation before the current one has actually started
+ setCurrentAnimation(index);
+ }
+
+ //we update currentAnimationIndex in case it has changed (the animation pointer is still valid)
+ currentAnimationIndex = animations.indexOf(currentAnimation);
+
+ if (index < currentAnimationIndex || currentLoop != 0) {
+ qWarning("QSequentialGroup::insertAnimationAt only supports to add animations after the current one.");
+ return; //we're not affected because it is added after the current one
+ }
+}
+
+/*!
+ \internal
+ This method is called whenever an animation is removed from
+ the group at index \a index. The animation is no more listed when this
+ method is called.
+*/
+void QSequentialAnimationGroupPrivate::animationRemovedAt(int index)
+{
+ Q_Q(QSequentialAnimationGroup);
+ QAnimationGroupPrivate::animationRemovedAt(index);
+
+ Q_ASSERT(currentAnimation); // currentAnimation should always be set
+
+ if (actualDuration.size() > index)
+ actualDuration.removeAt(index);
+
+ const int currentIndex = animations.indexOf(currentAnimation);
+ if (currentIndex == -1) {
+ //we're removing the current animation, let's update it to another one
+ if (index < animations.count())
+ setCurrentAnimation(index); //let's try to take the next one
+ else if (index > 0)
+ setCurrentAnimation(index - 1);
+ else// case all animations were removed
+ setCurrentAnimation(-1);
+ } else if (currentAnimationIndex > index) {
+ currentAnimationIndex--;
+ }
+
+ // duration of the previous animations up to the current animation
+ currentTime = 0;
+ for (int i = 0; i < currentAnimationIndex; ++i) {
+ const int current = animationActualTotalDuration(i);
+ currentTime += current;
+ }
+
+ if (currentIndex != -1) {
+ //the current animation is not the one being removed
+ //so we add its current time to the current time of this group
+ currentTime += QAbstractAnimationPrivate::get(currentAnimation)->totalCurrentTime;
+ }
+
+ //let's also update the total current time
+ totalCurrentTime = currentTime + loopCount * q->duration();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qsequentialanimationgroup.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qsequentialanimationgroup.h b/src/corelib/animation/qsequentialanimationgroup.h
new file mode 100644
index 0000000..4c52d1b
--- /dev/null
+++ b/src/corelib/animation/qsequentialanimationgroup.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSEQUENTIALANIMATIONGROUP_H
+#define QSEQUENTIALANIMATIONGROUP_H
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qanimationgroup.h"
+#else
+# include <QtCore/qanimationgroup.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QPauseAnimation;
+class QSequentialAnimationGroupPrivate;
+
+class Q_CORE_EXPORT QSequentialAnimationGroup : public QAnimationGroup
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractAnimation* currentAnimation READ currentAnimation NOTIFY currentAnimationChanged)
+
+public:
+ QSequentialAnimationGroup(QObject *parent = 0);
+ ~QSequentialAnimationGroup();
+
+ QPauseAnimation *addPause(int msecs);
+ QPauseAnimation *insertPauseAt(int index, int msecs);
+
+ QAbstractAnimation *currentAnimation() const;
+ int duration() const;
+
+Q_SIGNALS:
+ void currentAnimationChanged(QAbstractAnimation *current);
+
+protected:
+ QSequentialAnimationGroup(QSequentialAnimationGroupPrivate &dd, QObject *parent);
+ bool event(QEvent *event);
+
+ void updateCurrentTime(int msecs);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ void updateDirection(QAbstractAnimation::Direction direction);
+
+private:
+ Q_DISABLE_COPY(QSequentialAnimationGroup)
+ Q_DECLARE_PRIVATE(QSequentialAnimationGroup)
+ Q_PRIVATE_SLOT(d_func(), void _q_uncontrolledAnimationFinished())
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QSEQUENTIALANIMATIONGROUP_H
diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h
new file mode 100644
index 0000000..3ac90f8
--- /dev/null
+++ b/src/corelib/animation/qsequentialanimationgroup_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSEQUENTIALANIMATIONGROUP_P_H
+#define QSEQUENTIALANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qsequentialanimationgroup.h"
+#include "qanimationgroup_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+class QSequentialAnimationGroupPrivate : public QAnimationGroupPrivate
+{
+ Q_DECLARE_PUBLIC(QSequentialAnimationGroup)
+public:
+ QSequentialAnimationGroupPrivate()
+ : currentAnimation(0), currentAnimationIndex(-1), lastLoop(0)
+ { }
+
+
+ struct AnimationIndex
+ {
+ AnimationIndex() : index(0), timeOffset(0) {}
+ // index points to the animation at timeOffset, skipping 0 duration animations.
+ // Note that the index semantic is slightly different depending on the direction.
+ int index; // the index of the animation in timeOffset
+ int timeOffset; // time offset when the animation at index starts.
+ };
+
+ int animationActualTotalDuration(int index) const;
+ AnimationIndex indexForTime(int msecs) const;
+
+ void setCurrentAnimation(int index, bool intermediate = false);
+ void activateCurrentAnimation(bool intermediate = false);
+
+ void animationInsertedAt(int index);
+ void animationRemovedAt(int index);
+
+ bool atEnd() const;
+
+ QAbstractAnimation *currentAnimation;
+ int currentAnimationIndex;
+
+ // this is the actual duration of uncontrolled animations
+ // it helps seeking and even going forward
+ QList<int> actualDuration;
+
+ void restart();
+ int lastLoop;
+
+ // handle time changes
+ void rewindForwards(const AnimationIndex &newAnimationIndex);
+ void advanceForwards(const AnimationIndex &newAnimationIndex);
+
+ // private slot
+ void _q_uncontrolledAnimationFinished();
+};
+
+QT_END_NAMESPACE
+
+#endif //QSEQUENTIALANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
new file mode 100644
index 0000000..5c4339d
--- /dev/null
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -0,0 +1,645 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_ANIMATION
+
+#include "qvariantanimation.h"
+#include "qvariantanimation_p.h"
+
+#include <QtCore/QRect>
+#include <QtCore/QLineF>
+#include <QtCore/QLine>
+#include <QtCore/QReadWriteLock>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVariantAnimation
+ \ingroup group_animation
+ \brief The QVariantAnimation class provides an abstract base class for animations.
+ \since 4.5
+ \preliminary
+
+ This class is part of \l{The Animation Framework}. It serves as a
+ base class for property and item animations, with functions for
+ shared functionality.
+
+ QVariantAnimation cannot be used directly as it is an abstract
+ class; it does not implement
+ \l{QAbstractAnimation::}{updateCurrentValue()} from
+ QAbstractAnimation. The class performs interpolation over
+ \l{QVariant}s, but leaves using the interpolated values to its
+ subclasses. Currently, Qt provides QPropertyAnimation, which
+ animates Qt \l{Qt's Property System}{properties}. See the
+ QPropertyAnimation class description if you wish to animate such
+ properties.
+
+ You can then set start and end values for the property by calling
+ setStartValue() and setEndValue(), and finally call start() to
+ start the animation. QVariantAnimation will interpolate the
+ property of the target object and emit valueChanged(). To react to
+ a change in the current value you have to reimplement the
+ updateCurrentValue() virtual function.
+
+ It is also possible to set values at specified steps situated
+ between the start and end value. The interpolation will then
+ touch these points at the specified steps. Note that the start and
+ end values are defined as the key values at 0.0 and 1.0.
+
+ There are two ways to affect how QVariantAnimation interpolates
+ the values. You can set an easing curve by calling
+ setEasingCurve(), and configure the duration by calling
+ setDuration(). You can change how the QVariants are interpolated
+ by creating a subclass of QVariantAnimation, and reimplementing
+ the virtual interpolated() function.
+
+ Subclassing QVariantAnimation can be an alternative if you have
+ \l{QVariant}s that you do not wish to declare as Qt properties.
+ Note, however, that you in most cases will be better off declaring
+ your QVariant as a property.
+
+ Not all QVariant types are supported. Below is a list of currently
+ supported QVariant types:
+
+ \list
+ \o \l{QMetaType::}{Int}
+ \o \l{QMetaType::}{Double}
+ \o \l{QMetaType::}{Float}
+ \o \l{QMetaType::}{QLine}
+ \o \l{QMetaType::}{QLineF}
+ \o \l{QMetaType::}{QPoint}
+ \o \l{QMetaType::}{QSize}
+ \o \l{QMetaType::}{QSizeF}
+ \o \l{QMetaType::}{QRect}
+ \o \l{QMetaType::}{QRectF}
+ \endlist
+
+ If you need to interpolate other variant types, including custom
+ types, you have to implement interpolation for these yourself.
+ You do this by reimplementing interpolated(), which returns
+ interpolation values for the value being interpolated.
+
+ \omit We need some snippets around here. \endomit
+
+ \sa QPropertyAnimation, QAbstractAnimation, {The Animation Framework}
+*/
+
+/*!
+ \fn void QVariantAnimation::valueChanged(const QVariant &value)
+
+ QVariantAnimation emits this signal whenever the current \a value changes.
+
+ \sa currentValue, startValue, endValue
+*/
+
+static bool animationValueLessThan(const QVariantAnimation::KeyValue &p1, const QVariantAnimation::KeyValue &p2)
+{
+ return p1.first < p2.first;
+}
+
+template<> Q_INLINE_TEMPLATE QRect _q_interpolate(const QRect &f, const QRect &t, qreal progress)
+{
+ QRect ret;
+ ret.setCoords(_q_interpolate(f.left(), t.left(), progress),
+ _q_interpolate(f.top(), t.top(), progress),
+ _q_interpolate(f.right(), t.right(), progress),
+ _q_interpolate(f.bottom(), t.bottom(), progress));
+ return ret;
+}
+
+template<> Q_INLINE_TEMPLATE QRectF _q_interpolate(const QRectF &f, const QRectF &t, qreal progress)
+{
+ qreal x1, y1, w1, h1;
+ f.getRect(&x1, &y1, &w1, &h1);
+ qreal x2, y2, w2, h2;
+ t.getRect(&x2, &y2, &w2, &h2);
+ return QRectF( _q_interpolate(x1, x2, progress), _q_interpolate(y1, y2, progress),
+ _q_interpolate(w1, w2, progress), _q_interpolate(h1, h2, progress));
+}
+
+template<> Q_INLINE_TEMPLATE QLine _q_interpolate(const QLine &f, const QLine &t, qreal progress)
+{
+ return QLine( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
+}
+
+template<> Q_INLINE_TEMPLATE QLineF _q_interpolate(const QLineF &f, const QLineF &t, qreal progress)
+{
+ return QLineF( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
+}
+
+void QVariantAnimationPrivate::convertValues(int t)
+{
+ //this ensures that all the keyValues are of type t
+ for (int i = 0; i < keyValues.count(); ++i) {
+ QVariantAnimation::KeyValue &pair = keyValues[i];
+ if (pair.second.userType() != t)
+ pair.second.convert(static_cast<QVariant::Type>(t));
+ }
+ currentInterval.start.first = 2; // this will force the refresh
+ interpolator = 0; // if the type changed we need to update the interpolator
+}
+
+/*!
+ \fn void QVariantAnimation::updateCurrentValue(const QVariant &value) = 0;
+ This pure virtual function is called when the animated value is changed.
+ \a value is the new value.
+*/
+
+void QVariantAnimationPrivate::updateCurrentValue()
+{
+ Q_Q(QVariantAnimation);
+ const qreal progress = easing.valueForProgress(((duration == 0) ? qreal(1) : qreal(currentTime) / qreal(duration)));
+
+ if (progress < currentInterval.start.first || progress > currentInterval.end.first) {
+ //let's update currentInterval
+ QVariantAnimation::KeyValues::const_iterator itStart = qLowerBound(keyValues.constBegin(), keyValues.constEnd(), qMakePair(progress, QVariant()), animationValueLessThan);
+ QVariantAnimation::KeyValues::const_iterator itEnd = itStart;
+
+ // If we are at the end we should continue to use the last keyValues in case of extrapolation (progress > 1.0).
+ // This is because the easing function can return a value slightly outside the range [0, 1]
+ if (itStart != keyValues.constEnd()) {
+
+ //this can't happen because we always prepend the default start value there
+ if (itStart == keyValues.begin()) {
+ ++itEnd;
+ if (itEnd == keyValues.constEnd())
+ return; //there is no upper bound
+ } else {
+ --itStart;
+ }
+
+ //update all the values of the currentInterval
+ currentInterval.start = *itStart;
+ currentInterval.end = *itEnd;
+ }
+ }
+
+ const qreal startProgress = currentInterval.start.first,
+ endProgress = currentInterval.end.first;
+ const qreal localProgress = (progress - startProgress) / (endProgress - startProgress);
+
+ QVariant ret = q->interpolated(currentInterval.start.second,
+ currentInterval.end.second,
+ localProgress);
+ qSwap(currentValue, ret);
+ q->updateCurrentValue(currentValue);
+#ifndef QT_EXPERIMENTAL_SOLUTION
+ if (connectedSignals & changedSignalMask)
+#endif
+ if (currentValue != ret) {
+ //the value has changed
+ emit q->valueChanged(currentValue);
+ }
+}
+
+
+QVariant QVariantAnimationPrivate::valueAt(qreal step) const
+{
+ QVariantAnimation::KeyValues::const_iterator result =
+ qBinaryFind(keyValues.begin(), keyValues.end(), qMakePair(step, QVariant()), animationValueLessThan);
+ if (result != keyValues.constEnd())
+ return result->second;
+
+ return QVariant();
+}
+
+
+void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value)
+{
+ if (step < qreal(0.0) || step > qreal(1.0)) {
+ qWarning("QVariantAnimation::setValueAt: invalid step = %f", step);
+ return;
+ }
+
+ QVariantAnimation::KeyValue pair(step, value);
+
+ QVariantAnimation::KeyValues::iterator result = qLowerBound(keyValues.begin(), keyValues.end(), pair, animationValueLessThan);
+ if (result == keyValues.end() || result->first != step) {
+ keyValues.insert(result, pair);
+ } else {
+ if (value.isValid())
+ result->second = value; //remove the previous value
+ else if (step == 0 && !hasStartValue && defaultStartValue.isValid())
+ result->second = defaultStartValue; //we reset to the default start value
+ else
+ keyValues.erase(result); //replace the previous value
+ }
+
+ currentInterval.start.first = 2; // this will force the refresh
+ updateCurrentValue();
+}
+
+void QVariantAnimationPrivate::setDefaultStartValue(const QVariant &value)
+{
+ defaultStartValue = value;
+ if (!hasStartValue)
+ setValueAt(0, value);
+}
+
+/*!
+ Construct a QVariantAnimation object. \a parent is passed to QAbstractAnimation's
+ constructor.
+*/
+QVariantAnimation::QVariantAnimation(QObject *parent) : QAbstractAnimation(*new QVariantAnimationPrivate, parent)
+{
+ d_func()->init();
+}
+
+/*!
+ \internal
+*/
+QVariantAnimation::QVariantAnimation(QVariantAnimationPrivate &dd, QObject *parent) : QAbstractAnimation(dd, parent)
+{
+ d_func()->init();
+}
+
+/*!
+ Destroys the animation.
+*/
+QVariantAnimation::~QVariantAnimation()
+{
+}
+
+/*!
+ \property QVariantAnimation::easingCurve
+ \brief the easing curve of the animation
+
+ This property defines the easing curve of the animation. By
+ default, a linear easing curve is used, resulting in linear
+ interpolation. Other curves are provided, for instance,
+ QEasingCurve::InCirc, which provides a circular entry curve.
+ Another example is QEasingCurve::InOutElastic, which provides an
+ elastic effect on the values of the interpolated variant.
+
+ The easing curve is used with the interpolator, the interpolated()
+ virtual function, the animation's duration, and iterationCount, to
+ control how the current value changes as the animation progresses.
+*/
+QEasingCurve QVariantAnimation::easingCurve() const
+{
+ Q_D(const QVariantAnimation);
+ return d->easing;
+}
+
+void QVariantAnimation::setEasingCurve(const QEasingCurve &easing)
+{
+ Q_D(QVariantAnimation);
+ d->easing = easing;
+ d->updateCurrentValue();
+}
+
+Q_GLOBAL_STATIC(QVector<QVariantAnimation::Interpolator>, registeredInterpolators)
+Q_GLOBAL_STATIC(QReadWriteLock, registeredInterpolatorsLock)
+
+/*!
+ \fn void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
+ \relates QVariantAnimation
+ \threadsafe
+
+ Registers a custom interpolator \a func for the template type \c{T}.
+ The interpolator has to be registered before the animation is constructed.
+ To unregister (and use the default interpolator) set \a func to 0.
+ */
+
+/*!
+ \internal
+ \typedef QVariantAnimation::Interpolator
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+ \code
+ QVariant myInterpolator(const QVariant &from, const QVariant &to, qreal progress);
+ \endcode
+
+*/
+
+/*! \internal
+ * Registers a custom interpolator \a func for the specific \a interpolationType.
+ * The interpolator has to be registered before the animation is constructed.
+ * To unregister (and use the default interpolator) set \a func to 0.
+ */
+void QVariantAnimation::registerInterpolator(QVariantAnimation::Interpolator func, int interpolationType)
+{
+ // will override any existing interpolators
+ QWriteLocker locker(registeredInterpolatorsLock());
+ if (int(interpolationType) >= registeredInterpolators()->count())
+ registeredInterpolators()->resize(int(interpolationType) + 1);
+ registeredInterpolators()->replace(interpolationType, func);
+}
+
+
+template<typename T> static inline QVariantAnimation::Interpolator castToInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
+{
+ return reinterpret_cast<QVariantAnimation::Interpolator>(func);
+}
+
+QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int interpolationType)
+{
+ QReadLocker locker(registeredInterpolatorsLock());
+ QVariantAnimation::Interpolator ret = 0;
+ if (interpolationType < registeredInterpolators()->count()) {
+ ret = registeredInterpolators()->at(interpolationType);
+ if (ret) return ret;
+ }
+
+ switch(interpolationType)
+ {
+ case QMetaType::Int:
+ return castToInterpolator(_q_interpolateVariant<int>);
+ case QMetaType::Double:
+ return castToInterpolator(_q_interpolateVariant<double>);
+ case QMetaType::Float:
+ return castToInterpolator(_q_interpolateVariant<float>);
+ case QMetaType::QLine:
+ return castToInterpolator(_q_interpolateVariant<QLine>);
+ case QMetaType::QLineF:
+ return castToInterpolator(_q_interpolateVariant<QLineF>);
+ case QMetaType::QPoint:
+ return castToInterpolator(_q_interpolateVariant<QPoint>);
+ case QMetaType::QPointF:
+ return castToInterpolator(_q_interpolateVariant<QPointF>);
+ case QMetaType::QSize:
+ return castToInterpolator(_q_interpolateVariant<QSize>);
+ case QMetaType::QSizeF:
+ return castToInterpolator(_q_interpolateVariant<QSizeF>);
+ case QMetaType::QRect:
+ return castToInterpolator(_q_interpolateVariant<QRect>);
+ case QMetaType::QRectF:
+ return castToInterpolator(_q_interpolateVariant<QRectF>);
+ default:
+ return 0; //this type is not handled
+ }
+}
+
+/*!
+ \property QVariantAnimation::duration
+ \brief the duration of the animation
+
+ This property describes the duration in milliseconds of the
+ animation. The default duration is 250 milliseconds.
+
+ \sa QAbstractAnimation::duration()
+ */
+int QVariantAnimation::duration() const
+{
+ Q_D(const QVariantAnimation);
+ return d->duration;
+}
+
+void QVariantAnimation::setDuration(int msecs)
+{
+ Q_D(QVariantAnimation);
+ if (msecs < 0) {
+ qWarning("QVariantAnimation::setDuration: cannot set a negative duration");
+ return;
+ }
+ if (d->duration == msecs)
+ return;
+ d->duration = msecs;
+ d->updateCurrentValue();
+}
+
+/*!
+ \property QVariantAnimation::startValue
+ \brief the optional start value of the animation
+
+ This property describes the optional start value of the animation. If
+ omitted, or if a null QVariant is assigned as the start value, the
+ animation will use the current position of the end when the animation
+ is started.
+
+ \sa endValue
+*/
+QVariant QVariantAnimation::startValue() const
+{
+ return keyValueAt(0);
+}
+
+void QVariantAnimation::setStartValue(const QVariant &value)
+{
+ setKeyValueAt(0, value);
+}
+
+/*!
+ \property QVariantAnimation::endValue
+ \brief the end value of the animation
+
+ This property describes the end value of the animation.
+
+ \sa startValue
+ */
+QVariant QVariantAnimation::endValue() const
+{
+ return keyValueAt(1);
+}
+
+void QVariantAnimation::setEndValue(const QVariant &value)
+{
+ setKeyValueAt(1, value);
+}
+
+
+/*!
+ Returns the key frame value for the given \a step. The given \a step
+ must be in the range 0 to 1. If there is no KeyValue for \a step,
+ it returns an invalid QVariant.
+
+ \sa keyValues(), setKeyValueAt()
+*/
+QVariant QVariantAnimation::keyValueAt(qreal step) const
+{
+ Q_D(const QVariantAnimation);
+ if (step == 0 && !d->hasStartValue)
+ return QVariant(); //special case where we don't have an explicit startValue
+
+ return d->valueAt(step);
+}
+
+/*!
+ \typedef QVariantAnimation::KeyValue
+
+ This is a typedef for QPair<qreal, QVariant>.
+*/
+/*!
+ \typedef QVariantAnimation::KeyValues
+
+ This is a typedef for QVector<KeyValue>
+*/
+
+/*!
+ Creates a key frame at the given \a step with the given \a value.
+ The given \a step must be in the range 0 to 1.
+
+ \sa setKeyValues(), keyValueAt()
+*/
+void QVariantAnimation::setKeyValueAt(qreal step, const QVariant &value)
+{
+ Q_D(QVariantAnimation);
+ if (step == 0)
+ d->hasStartValue = value.isValid();
+ d->setValueAt(step, value);
+}
+
+/*!
+ Returns the key frames of this animation.
+
+ \sa keyValueAt(), setKeyValues()
+*/
+QVariantAnimation::KeyValues QVariantAnimation::keyValues() const
+{
+ Q_D(const QVariantAnimation);
+ QVariantAnimation::KeyValues ret = d->keyValues;
+ //in case we added the default start value, we remove it
+ if (!d->hasStartValue && !ret.isEmpty() && ret.at(0).first == 0)
+ ret.remove(0);
+ return ret;
+}
+
+/*!
+ Replaces the current set of key frames with the given \a keyValues.
+ the step of the key frames must be in the range 0 to 1.
+
+ \sa keyValues(), keyValueAt()
+*/
+void QVariantAnimation::setKeyValues(const KeyValues &keyValues)
+{
+ Q_D(QVariantAnimation);
+ d->keyValues = keyValues;
+ qSort(d->keyValues.begin(), d->keyValues.end(), animationValueLessThan);
+ d->currentInterval.start.first = 2; // this will force the refresh
+ d->hasStartValue = !d->keyValues.isEmpty() && d->keyValues.at(0).first == 0;
+}
+
+/*!
+ \property QVariantAnimation::currentValue
+ \brief the current value of the animation.
+
+ This property describes the current value; an interpolated value
+ between the \l{startValue}{start value} and the \l{endValue}{end
+ value}, using the current time for progress. The value itself is
+ obtained from interpolated(), which is called repeatedly as the
+ animation is running.
+
+ QVariantAnimation calls the virtual updateCurrentValue() function
+ when the current value changes. This is particularly useful for
+ subclasses that need to track updates. For example,
+ QPropertyAnimation uses this function to animate Qt \l{Qt's
+ Property System}{properties}.
+
+ \sa startValue, endValue
+*/
+QVariant QVariantAnimation::currentValue() const
+{
+ Q_D(const QVariantAnimation);
+ if (!d->currentValue.isValid())
+ const_cast<QVariantAnimationPrivate*>(d)->updateCurrentValue();
+ return d->currentValue;
+}
+
+/*!
+ \reimp
+ */
+bool QVariantAnimation::event(QEvent *event)
+{
+ return QAbstractAnimation::event(event);
+}
+
+/*!
+ \reimp
+*/
+void QVariantAnimation::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_UNUSED(oldState);
+ Q_UNUSED(newState);
+ Q_D(QVariantAnimation);
+ d->currentValue = QVariant(); // this will force the refresh
+}
+
+/*!
+
+ This virtual function returns the linear interpolation between
+ variants \a from and \a to, at \a progress, usually a value
+ between 0 and 1. You can reimplement this function in a subclass
+ of QVariantAnimation to provide your own interpolation algorithm.
+
+ Note that in order for the interpolation to work with a
+ QEasingCurve that return a value smaller than 0 or larger than 1
+ (such as QEasingCurve::InBack) you should make sure that it can
+ extrapolate. If the semantic of the datatype does not allow
+ extrapolation this function should handle that gracefully.
+
+ You should call the QVariantAnimation implementation of this
+ function if you want your class to handle the types already
+ supported by Qt (see class QVariantAnimation description for a
+ list of supported types).
+
+ \sa QEasingCurve
+ */
+QVariant QVariantAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const
+{
+ Q_D(const QVariantAnimation);
+ if (d->interpolator == 0) {
+ if (from.userType() == to.userType())
+ d->interpolator = QVariantAnimationPrivate::getInterpolator(from.userType());
+ if (d->interpolator == 0) //no interpolator found
+ return QVariant();
+ }
+
+ return d->interpolator(from.constData(), to.constData(), progress);
+}
+
+/*!
+ \reimp
+ */
+void QVariantAnimation::updateCurrentTime(int msecs)
+{
+ Q_D(QVariantAnimation);
+ Q_UNUSED(msecs);
+ d->updateCurrentValue();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qvariantanimation.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qvariantanimation.h b/src/corelib/animation/qvariantanimation.h
new file mode 100644
index 0000000..69dbbf3
--- /dev/null
+++ b/src/corelib/animation/qvariantanimation.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATION_H
+#define QANIMATION_H
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qabstractanimation.h"
+# include "qeasingcurve.h"
+#else
+# include <QtCore/qeasingcurve.h>
+# include <QtCore/qabstractanimation.h>
+#endif
+#include <QtCore/qvector.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qpair.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QVariantAnimationPrivate;
+class Q_CORE_EXPORT QVariantAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(QVariant startValue READ startValue WRITE setStartValue)
+ Q_PROPERTY(QVariant endValue READ endValue WRITE setEndValue)
+ Q_PROPERTY(QVariant currentValue READ currentValue NOTIFY currentValueChanged)
+ Q_PROPERTY(int duration READ duration WRITE setDuration)
+ Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve)
+
+public:
+ typedef QPair<qreal, QVariant> KeyValue;
+ typedef QVector<KeyValue> KeyValues;
+
+ QVariantAnimation(QObject *parent = 0);
+ ~QVariantAnimation();
+
+ QVariant startValue() const;
+ void setStartValue(const QVariant &value);
+
+ QVariant endValue() const;
+ void setEndValue(const QVariant &value);
+
+ QVariant keyValueAt(qreal step) const;
+ void setKeyValueAt(qreal step, const QVariant &value);
+
+ KeyValues keyValues() const;
+ void setKeyValues(const KeyValues &values);
+
+ QVariant currentValue() const;
+
+ int duration() const;
+ void setDuration(int msecs);
+
+ QEasingCurve easingCurve() const;
+ void setEasingCurve(const QEasingCurve &easing);
+
+ typedef QVariant (*Interpolator)(const void *from, const void *to, qreal progress);
+
+Q_SIGNALS:
+ void valueChanged(const QVariant &value);
+
+protected:
+ QVariantAnimation(QVariantAnimationPrivate &dd, QObject *parent = 0);
+ bool event(QEvent *event);
+
+ void updateCurrentTime(int msecs);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+
+ virtual void updateCurrentValue(const QVariant &value) = 0;
+ virtual QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const;
+
+private:
+ template <typename T> friend void qRegisterAnimationInterpolator(QVariant (*func)(const T &, const T &, qreal));
+ static void registerInterpolator(Interpolator func, int interpolationType);
+
+ Q_DISABLE_COPY(QVariantAnimation)
+ Q_DECLARE_PRIVATE(QVariantAnimation)
+};
+
+template <typename T>
+static void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress)) {
+ QVariantAnimation::registerInterpolator(reinterpret_cast<QVariantAnimation::Interpolator>(func), qMetaTypeId<T>());
+}
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QANIMATION_H
diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h
new file mode 100644
index 0000000..14a3ef6
--- /dev/null
+++ b/src/corelib/animation/qvariantanimation_p.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATION_P_H
+#define QANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qvariantanimation.h"
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qeasingcurve.h"
+#else
+# include <QtCore/qeasingcurve.h>
+#endif
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qvector.h>
+
+#include "qabstractanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QVariantAnimationPrivate : public QAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QVariantAnimation)
+public:
+
+ QVariantAnimationPrivate() : duration(250), hasStartValue(false)
+ {
+ }
+
+ void init()
+ {
+ //we keep the mask so that we emit valueChanged only when needed (for performance reasons)
+ changedSignalMask = (1 << q_func()->metaObject()->indexOfSignal("valueChanged(QVariant)"));
+ currentInterval.start.first = currentInterval.end.first = 2; //will force the initial refresh
+ interpolator = 0;
+ }
+
+ static QVariantAnimationPrivate *get(QVariantAnimation *q)
+ {
+ return q->d_func();
+ }
+
+ void setDefaultStartValue(const QVariant &value);
+
+ int duration;
+ QEasingCurve easing;
+
+ QVariantAnimation::KeyValues keyValues;
+ QVariant currentValue;
+ QVariant defaultStartValue;
+ bool hasStartValue;
+
+ //this is used to keep track of the KeyValue interval in which we currently are
+ struct
+ {
+ QVariantAnimation::KeyValue start, end;
+ } currentInterval;
+
+ mutable QVariantAnimation::Interpolator interpolator;
+
+ quint32 changedSignalMask;
+
+ void updateCurrentValue();
+ void setValueAt(qreal, const QVariant &);
+ QVariant valueAt(qreal step) const;
+ void convertValues(int t);
+
+ static QVariantAnimation::Interpolator getInterpolator(int interpolationType);
+};
+
+//this should make the interpolation faster
+template<typename T> inline T _q_interpolate(const T &f, const T &t, qreal progress)
+{
+ return T(f + (t - f) * progress);
+}
+
+template<typename T > inline QVariant _q_interpolateVariant(const T &from, const T &to, qreal progress)
+{
+ return _q_interpolate(from, to, progress);
+}
+
+
+QT_END_NAMESPACE
+
+#endif //QANIMATION_P_H
diff --git a/src/corelib/arch/qatomic_bootstrap.h b/src/corelib/arch/qatomic_bootstrap.h
index 7584b84..af76903 100644
--- a/src/corelib/arch/qatomic_bootstrap.h
+++ b/src/corelib/arch/qatomic_bootstrap.h
@@ -92,6 +92,20 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValu
return false;
}
+template <typename T>
+Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
+{
+ T *currentValue = _q_value;
+ _q_value = newValue;
+ return currentValue;
+}
+
+template <typename T>
+Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
+{
+ return testAndSetOrdered(expectedValue, newValue);
+}
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index f99d57f..db51d43 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -5,6 +5,7 @@ DEFINES += QT_BUILD_CORE_LIB QT_NO_USING_NAMESPACE
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x67000000
include(../qbase.pri)
+include(animation/animation.pri)
include(arch/arch.pri)
include(concurrent/concurrent.pri)
include(global/global.pri)
@@ -14,6 +15,7 @@ include(io/io.pri)
include(plugin/plugin.pri)
include(kernel/kernel.pri)
include(codecs/codecs.pri)
+include(statemachine/statemachine.pri)
include(xml/xml.pri)
mac|darwin:LIBS += -framework ApplicationServices
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 3990c7d..41265ba 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -128,6 +128,22 @@ namespace QT_NAMESPACE {}
#endif /* __cplusplus */
+/**
+ * For animation framework to work seamlessly as a solution
+ */
+#if 0
+# define QT_EXPERIMENTAL_BEGIN_NAMESPACE namespace QtExperimental {
+# define QT_EXPERIMENTAL_END_NAMESPACE }
+# define QT_EXPERIMENTAL_USE_NAMESPACE using namespace QtExperimental;
+# define QT_EXPERIMENTAL_PREPEND_NAMESPACE(name) QtExperimental::name
+namespace QtExperimental {}
+#else
+# define QT_EXPERIMENTAL_BEGIN_NAMESPACE
+# define QT_EXPERIMENTAL_END_NAMESPACE
+# define QT_EXPERIMENTAL_USE_NAMESPACE
+# define QT_EXPERIMENTAL_PREPEND_NAMESPACE(name) name
+#endif
+
#if defined(Q_OS_MAC) && !defined(Q_CC_INTEL)
#define QT_BEGIN_HEADER extern "C++" {
#define QT_END_HEADER }
@@ -1137,6 +1153,11 @@ class QDataStream;
# else
# define Q_SVG_EXPORT Q_DECL_IMPORT
# endif
+# if defined(QT_BUILD_DECLARATIVE_LIB)
+# define Q_DECLARATIVE_EXPORT Q_DECL_EXPORT
+# else
+# define Q_DECLARATIVE_EXPORT Q_DECL_IMPORT
+# endif
# if defined(QT_BUILD_OPENGL_LIB)
# define Q_OPENGL_EXPORT Q_DECL_EXPORT
# else
@@ -1179,6 +1200,7 @@ class QDataStream;
# define Q_SQL_EXPORT Q_DECL_IMPORT
# define Q_NETWORK_EXPORT Q_DECL_IMPORT
# define Q_SVG_EXPORT Q_DECL_IMPORT
+# define Q_DECLARATIVE_EXPORT Q_DECL_IMPORT
# define Q_CANVAS_EXPORT Q_DECL_IMPORT
# define Q_OPENGL_EXPORT Q_DECL_IMPORT
# define Q_XML_EXPORT Q_DECL_IMPORT
@@ -1205,6 +1227,7 @@ class QDataStream;
# define Q_SQL_EXPORT Q_DECL_EXPORT
# define Q_NETWORK_EXPORT Q_DECL_EXPORT
# define Q_SVG_EXPORT Q_DECL_EXPORT
+# define Q_DECLARATIVE_EXPORT Q_DECL_EXPORT
# define Q_OPENGL_EXPORT Q_DECL_EXPORT
# define Q_XML_EXPORT Q_DECL_EXPORT
# define Q_XMLPATTERNS_EXPORT Q_DECL_EXPORT
@@ -1217,6 +1240,7 @@ class QDataStream;
# define Q_SQL_EXPORT
# define Q_NETWORK_EXPORT
# define Q_SVG_EXPORT
+# define Q_DECLARATIVE_EXPORT
# define Q_OPENGL_EXPORT
# define Q_XML_EXPORT
# define Q_XMLPATTERNS_EXPORT
@@ -2251,6 +2275,7 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf();
#define QT_MODULE_TEST 0x04000
#define QT_MODULE_DBUS 0x08000
#define QT_MODULE_SCRIPTTOOLS 0x10000
+#define QT_MODULE_DECLARATIVE 0x20000
/* Qt editions */
#define QT_EDITION_CONSOLE (QT_MODULE_CORE \
@@ -2278,6 +2303,7 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf();
| QT_MODULE_QT3SUPPORTLIGHT \
| QT_MODULE_QT3SUPPORT \
| QT_MODULE_SVG \
+ | QT_MODULE_DECLARATIVE \
| QT_MODULE_GRAPHICSVIEW \
| QT_MODULE_HELP \
| QT_MODULE_TEST \
@@ -2340,6 +2366,9 @@ QT_LICENSED_MODULE(Qt3Support)
#if (QT_EDITION & QT_MODULE_SVG)
QT_LICENSED_MODULE(Svg)
#endif
+#if (QT_EDITION & QT_MODULE_DECLARATIVE)
+QT_LICENSED_MODULE(Declarative)
+#endif
#if (QT_EDITION & QT_MODULE_ACTIVEQT)
QT_LICENSED_MODULE(ActiveQt)
#endif
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index d90ecae..3988289 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -12,7 +12,7 @@ HEADERS += \
kernel/qcoreevent.h \
kernel/qmetaobject.h \
kernel/qmetatype.h \
- kernel/qmimedata.h \
+ kernel/qmimedata.h \
kernel/qobject.h \
kernel/qobjectdefs.h \
kernel/qsignalmapper.h \
@@ -27,12 +27,13 @@ HEADERS += \
kernel/qvariant_p.h \
kernel/qmetaobject_p.h \
kernel/qobject_p.h \
- kernel/qcoreglobaldata_p.h \
- kernel/qsharedmemory.h \
+ kernel/qcoreglobaldata_p.h \
+ kernel/qsharedmemory.h \
kernel/qsharedmemory_p.h \
kernel/qsystemsemaphore.h \
kernel/qsystemsemaphore_p.h \
- kernel/qfunctions_p.h
+ kernel/qfunctions_p.h \
+ kernel/qmetaobjectbuilder_p.h
SOURCES += \
kernel/qabstracteventdispatcher.cpp \
@@ -43,7 +44,7 @@ SOURCES += \
kernel/qcoreevent.cpp \
kernel/qmetaobject.cpp \
kernel/qmetatype.cpp \
- kernel/qmimedata.cpp \
+ kernel/qmimedata.cpp \
kernel/qobject.cpp \
kernel/qobjectcleanuphandler.cpp \
kernel/qsignalmapper.cpp \
@@ -51,9 +52,10 @@ SOURCES += \
kernel/qtimer.cpp \
kernel/qtranslator.cpp \
kernel/qvariant.cpp \
- kernel/qcoreglobaldata.cpp \
- kernel/qsharedmemory.cpp \
- kernel/qsystemsemaphore.cpp
+ kernel/qcoreglobaldata.cpp \
+ kernel/qsharedmemory.cpp \
+ kernel/qsystemsemaphore.cpp \
+ kernel/qmetaobjectbuilder.cpp
win32 {
SOURCES += \
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp
index fd0e105..93a0985 100644
--- a/src/corelib/kernel/qabstractitemmodel.cpp
+++ b/src/corelib/kernel/qabstractitemmodel.cpp
@@ -467,6 +467,21 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel()
return qEmptyModel();
}
+const QHash<int,QByteArray> &QAbstractItemModelPrivate::defaultRoleNames()
+{
+ static QHash<int,QByteArray> roleNames;
+ if (roleNames.isEmpty()) {
+ roleNames[Qt::DisplayRole] = "display";
+ roleNames[Qt::DecorationRole] = "decoration";
+ roleNames[Qt::EditRole] = "edit";
+ roleNames[Qt::ToolTipRole] = "toolTip";
+ roleNames[Qt::StatusTipRole] = "statusTip";
+ roleNames[Qt::WhatsThisRole] = "whatsThis";
+ }
+
+ return roleNames;
+}
+
void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexData *data)
{
if (data->index.isValid()) {
@@ -1832,6 +1847,25 @@ QSize QAbstractItemModel::span(const QModelIndex &) const
}
/*!
+ Sets the model's role names to \a roleNames.
+*/
+void QAbstractItemModel::setRoleNames(const QHash<int,QByteArray> &roleNames)
+{
+ Q_D(QAbstractItemModel);
+ d->roleNames = roleNames;
+}
+
+/*!
+ Returns the model's role names.
+*/
+const QHash<int,QByteArray> &QAbstractItemModel::roleNames() const
+{
+ Q_D(const QAbstractItemModel);
+ qDebug() << "roles" << d->roleNames;
+ return d->roleNames;
+}
+
+/*!
Called to let the model know that it should submit whatever it has cached
to the permanent storage. Typically used for row editing.
diff --git a/src/corelib/kernel/qabstractitemmodel.h b/src/corelib/kernel/qabstractitemmodel.h
index b062768..00cd817 100644
--- a/src/corelib/kernel/qabstractitemmodel.h
+++ b/src/corelib/kernel/qabstractitemmodel.h
@@ -220,6 +220,9 @@ public:
Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const;
virtual QSize span(const QModelIndex &index) const;
+ void setRoleNames(const QHash<int,QByteArray> &roleNames);
+ const QHash<int,QByteArray> &roleNames() const;
+
#ifdef Q_NO_USING_KEYWORD
inline QObject *parent() const { return QObject::parent(); }
#else
diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h
index df1a6ce..10d3793 100644
--- a/src/corelib/kernel/qabstractitemmodel_p.h
+++ b/src/corelib/kernel/qabstractitemmodel_p.h
@@ -78,7 +78,7 @@ class Q_CORE_EXPORT QAbstractItemModelPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QAbstractItemModel)
public:
- QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1) {}
+ QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1), roleNames(defaultRoleNames()) {}
void removePersistentIndexData(QPersistentModelIndexData *data);
void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
void rowsInserted(const QModelIndex &parent, int first, int last);
@@ -143,6 +143,9 @@ public:
} persistent;
Qt::DropActions supportedDragActions;
+
+ QHash<int,QByteArray> roleNames;
+ static const QHash<int,QByteArray> &defaultRoleNames();
};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index 11a2d3c..bbd0695 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -264,6 +264,8 @@ QT_BEGIN_NAMESPACE
\omitvalue NetworkReplyUpdated
\omitvalue FutureCallOut
\omitvalue CocoaRequestModal
+ \omitvalue Wrapped
+ \omitvalue Signal
*/
/*!
@@ -288,7 +290,7 @@ QEvent::~QEvent()
/*!
\property QEvent::accepted
- the accept flag of the event object
+ \brief The accept flag of the event object
Setting the accept parameter indicates that the event receiver
wants the event. Unwanted events might be propagated to the parent
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index fa472e6..18188a8 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -44,6 +44,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qbytearray.h>
+#include <QtCore/qobjectdefs.h>
QT_BEGIN_HEADER
@@ -54,7 +55,9 @@ QT_MODULE(Core)
class QEventPrivate;
class Q_CORE_EXPORT QEvent // event base class
{
+ Q_GADGET
QDOC_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+ Q_ENUMS(Type)
public:
enum Type {
/*
@@ -266,7 +269,10 @@ public:
CocoaRequestModal = 190, // Internal for requesting an application modal Cocoa Window
MacGLClearDrawable = 191, // Internal Cocoa, the window has changed, so we must clear
- // 512 reserved for Qt Jambi's MetaCall event
+ Signal = 192,
+ Wrapped = 193,
+
+ // 512 reserved for Qt Jambi's MetaCall event
// 513 reserved for Qt Jambi's DeleteOnMainThread event
User = 1000, // first user event id
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index b65f956..7502842 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -159,7 +159,8 @@ enum PropertyFlags {
ResolveEditable = 0x00080000,
User = 0x00100000,
ResolveUser = 0x00200000,
- Notify = 0x00400000
+ Notify = 0x00400000,
+ Dynamic = 0x00800000
};
enum MethodFlags {
@@ -179,6 +180,10 @@ enum MethodFlags {
MethodScriptable = 0x40
};
+enum MetaObjectFlags {
+ DynamicMetaObject = 0x01
+};
+
struct QMetaObjectPrivate
{
int revision;
@@ -188,6 +193,7 @@ struct QMetaObjectPrivate
int propertyCount, propertyData;
int enumeratorCount, enumeratorData;
int constructorCount, constructorData;
+ int flags;
};
static inline const QMetaObjectPrivate *priv(const uint* data)
@@ -271,6 +277,17 @@ int QMetaObject::static_metacall(Call cl, int idx, void **argv) const
}
/*!
+ \internal
+*/
+int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
+{
+ if (QMetaObject *mo = object->d_ptr->metaObject)
+ return static_cast<QAbstractDynamicMetaObject*>(mo)->metaCall(cl, idx, argv);
+ else
+ return object->qt_metacall(cl, idx, argv);
+}
+
+/*!
\fn const char *QMetaObject::className() const
Returns the class name.
@@ -690,6 +707,14 @@ int QMetaObject::indexOfProperty(const char *name) const
}
m = m->d.superdata;
}
+
+ if (i == -1 && priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)){
+ QAbstractDynamicMetaObject *me =
+ const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this));
+
+ i = me->createProperty(name, 0);
+ }
+
return i;
}
@@ -1320,6 +1345,16 @@ int QMetaMethod::attributes() const
}
/*!
+ Returns this method's index.
+*/
+int QMetaMethod::methodIndex() const
+{
+ if (!mobj)
+ return -1;
+ return ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset();
+}
+
+/*!
Returns the access specification of this method (private,
protected, or public).
@@ -1519,7 +1554,7 @@ bool QMetaMethod::invoke(QObject *object,
// recompute the methodIndex by reversing the arithmetic in QMetaObject::property()
int methodIndex = ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset();
if (connectionType == Qt::DirectConnection) {
- return object->qt_metacall(QMetaObject::InvokeMetaMethod, methodIndex, param) < 0;
+ return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0;
} else {
if (returnValue.data()) {
qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in "
@@ -2029,6 +2064,16 @@ int QMetaProperty::userType() const
}
/*!
+ Returns this property's index.
+*/
+int QMetaProperty::propertyIndex() const
+{
+ if (!mobj)
+ return -1;
+ return idx + mobj->propertyOffset();
+}
+
+/*!
Returns true if the property's type is an enumeration value that
is used as a flag; otherwise returns false.
@@ -2133,9 +2178,8 @@ QVariant QMetaProperty::read(const QObject *object) const
value = QVariant(t, (void*)0);
argv[0] = value.data();
}
- const_cast<QObject*>(object)->qt_metacall(QMetaObject::ReadProperty,
- idx + mobj->propertyOffset(),
- argv);
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty,
+ idx + mobj->propertyOffset(), argv);
if (argv[1] == 0)
// "value" was changed
return value;
@@ -2200,7 +2244,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const
argv[0] = &v;
else
argv[0] = v.data();
- object->qt_metacall(QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv);
return true;
}
@@ -2217,7 +2261,7 @@ bool QMetaProperty::reset(QObject *object) const
if (!object || !mobj || !isResettable())
return false;
void *argv[] = { 0 };
- object->qt_metacall(QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv);
return true;
}
@@ -2329,8 +2373,8 @@ bool QMetaProperty::isDesignable(const QObject *object) const
bool b = flags & Designable;
if (object) {
void *argv[] = { &b };
- const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyDesignable,
- idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyDesignable,
+ idx + mobj->propertyOffset(), argv);
}
return b;
@@ -2355,8 +2399,8 @@ bool QMetaProperty::isScriptable(const QObject *object) const
bool b = flags & Scriptable;
if (object) {
void *argv[] = { &b };
- const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyScriptable,
- idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyScriptable,
+ idx + mobj->propertyOffset(), argv);
}
return b;
}
@@ -2379,8 +2423,8 @@ bool QMetaProperty::isStored(const QObject *object) const
bool b = flags & Stored;
if (object) {
void *argv[] = { &b };
- const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyStored,
- idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyStored,
+ idx + mobj->propertyOffset(), argv);
}
return b;
}
@@ -2406,13 +2450,24 @@ bool QMetaProperty::isUser(const QObject *object) const
bool b = flags & User;
if (object) {
void *argv[] = { &b };
- const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyUser,
- idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyUser,
+ idx + mobj->propertyOffset(), argv);
}
return b;
}
/*!
+ \internal
+*/
+bool QMetaProperty::isDynamic() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Dynamic;
+}
+
+/*!
\obsolete
Returns true if the property is editable for the given \a object;
@@ -2432,8 +2487,8 @@ bool QMetaProperty::isEditable(const QObject *object) const
bool b = flags & Editable;
if (object) {
void *argv[] = { &b };
- const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyEditable,
- idx + mobj->propertyOffset(), argv);
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyEditable,
+ idx + mobj->propertyOffset(), argv);
}
return b;
}
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
index 18c488a..26e8b53 100644
--- a/src/corelib/kernel/qmetaobject.h
+++ b/src/corelib/kernel/qmetaobject.h
@@ -69,6 +69,7 @@ public:
MethodType methodType() const;
enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 };
int attributes() const;
+ int methodIndex() const;
inline const QMetaObject *enclosingMetaObject() const { return mobj; }
@@ -178,6 +179,7 @@ public:
const char *typeName() const;
QVariant::Type type() const;
int userType() const;
+ int propertyIndex() const;
bool isReadable() const;
bool isWritable() const;
@@ -187,6 +189,7 @@ public:
bool isStored(const QObject *obj = 0) const;
bool isEditable(const QObject *obj = 0) const;
bool isUser(const QObject *obj = 0) const;
+ bool isDynamic() const;
bool isFlagType() const;
bool isEnumType() const;
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
new file mode 100644
index 0000000..5b8de93
--- /dev/null
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -0,0 +1,2450 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qmetaobjectbuilder_p.h"
+#include <QDebug>
+
+/*!
+ \class QMetaObjectBuilder
+ \brief The QMetaObjectBuilder class supports the building of QMetaObject objects at runtime.
+
+ See the QDynamicMetaObject class documentation for an example
+ of using this class.
+
+ \sa QDynamicMetaObject, QDynamicObject
+*/
+
+/*!
+ \enum QMetaObjectBuilder::AddMember
+ This enum defines which members of QMetaObject should be copied by QMetaObjectBuilder::addMetaObject()
+
+ \value ClassName Add the class name.
+ \value SuperClass Add the super class.
+ \value Methods Add methods that aren't signals or slots.
+ \value Signals Add signals.
+ \value Slots Add slots.
+ \value Constructors Add constructors.
+ \value Properties Add properties.
+ \value Enumerators Add enumerators.
+ \value ClassInfos Add items of class information.
+ \value RelatedMetaObjects Add related meta objects.
+ \value StaticMetacall Add the static metacall function.
+ \value PublicMethods Add public methods (ignored for signals).
+ \value ProtectedMethods Add protected methods (ignored for signals).
+ \value PrivateMethods All private methods (ignored for signals).
+ \value AllMembers Add all members.
+ \value AllPrimaryMembers Add everything except the class name, super class, and static metacall function.
+*/
+
+/*!
+ \enum QMetaObjectBuilder::MetaObjectFlag
+ This enum defines flags for the class being constructed.
+
+ \value DynamicMetaObject
+ */
+
+// copied from moc's generator.cpp
+uint qvariant_nameToType(const char* name)
+{
+ if (!name)
+ return 0;
+
+ if (strcmp(name, "QVariant") == 0)
+ return 0xffffffff;
+ if (strcmp(name, "QCString") == 0)
+ return QMetaType::QByteArray;
+ if (strcmp(name, "Q_LLONG") == 0)
+ return QMetaType::LongLong;
+ if (strcmp(name, "Q_ULLONG") == 0)
+ return QMetaType::ULongLong;
+ if (strcmp(name, "QIconSet") == 0)
+ return QMetaType::QIcon;
+
+ uint tp = QMetaType::type(name);
+ return tp < QMetaType::User ? tp : 0;
+}
+
+/*
+ Returns true if the type is a QVariant types.
+*/
+bool isVariantType(const char* type)
+{
+ return qvariant_nameToType(type) != 0;
+}
+
+// copied from qmetaobject.cpp
+// do not touch without touching the moc as well
+enum PropertyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resettable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+// Override = 0x00000200,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000,
+ User = 0x00100000,
+ ResolveUser = 0x00200000,
+ Notify = 0x00400000,
+ Dynamic = 0x00800000
+};
+
+enum MethodFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ AccessMask = 0x03, //mask
+
+ MethodMethod = 0x00,
+ MethodSignal = 0x04,
+ MethodSlot = 0x08,
+ MethodConstructor = 0x0c,
+ MethodTypeMask = 0x0c,
+
+ MethodCompatibility = 0x10,
+ MethodCloned = 0x20,
+ MethodScriptable = 0x40
+};
+
+struct QMetaObjectPrivate
+{
+ int revision;
+ int className;
+ int classInfoCount, classInfoData;
+ int methodCount, methodData;
+ int propertyCount, propertyData;
+ int enumeratorCount, enumeratorData;
+ int constructorCount, constructorData;
+ int flags;
+};
+
+static inline const QMetaObjectPrivate *priv(const uint* data)
+{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
+// end of copied lines from qmetaobject.cpp
+
+class QMetaMethodBuilderPrivate
+{
+public:
+ QMetaMethodBuilderPrivate
+ (QMetaMethod::MethodType _methodType,
+ const QByteArray& _signature,
+ const QByteArray& _returnType = QByteArray(),
+ QMetaMethod::Access _access = QMetaMethod::Public)
+ : signature(QMetaObject::normalizedSignature(_signature.constData())),
+ returnType(QMetaObject::normalizedType(_returnType)),
+ attributes(((int)_access) | (((int)_methodType) << 2))
+ {
+ }
+
+ QByteArray signature;
+ QByteArray returnType;
+ QList<QByteArray> parameterNames;
+ QByteArray tag;
+ int attributes;
+
+ QMetaMethod::MethodType methodType() const
+ {
+ return (QMetaMethod::MethodType)((attributes & MethodTypeMask) >> 2);
+ }
+
+ QMetaMethod::Access access() const
+ {
+ return (QMetaMethod::Access)(attributes & AccessMask);
+ }
+
+ void setAccess(QMetaMethod::Access value)
+ {
+ attributes = ((attributes & ~AccessMask) | (int)value);
+ }
+};
+
+class QMetaPropertyBuilderPrivate
+{
+public:
+ QMetaPropertyBuilderPrivate
+ (const QByteArray& _name, const QByteArray& _type, int notifierIdx=-1)
+ : name(_name),
+ type(QMetaObject::normalizedType(_type.constData())),
+ flags(Readable | Writable), notifySignal(-1)
+ {
+ if (notifierIdx >= 0) {
+ flags |= Notify;
+ notifySignal = notifierIdx;
+ }
+ }
+
+ QByteArray name;
+ QByteArray type;
+ int flags;
+ int notifySignal;
+
+ bool flag(int f) const
+ {
+ return ((flags & f) != 0);
+ }
+
+ void setFlag(int f, bool value)
+ {
+ if (value)
+ flags |= f;
+ else
+ flags &= ~f;
+ }
+};
+
+class QMetaEnumBuilderPrivate
+{
+public:
+ QMetaEnumBuilderPrivate(const QByteArray& _name)
+ : name(_name), isFlag(false)
+ {
+ }
+
+ QByteArray name;
+ bool isFlag;
+ QList<QByteArray> keys;
+ QList<int> values;
+};
+
+class QMetaObjectBuilderPrivate
+{
+public:
+ QMetaObjectBuilderPrivate()
+ : flags(0)
+ {
+ superClass = &QObject::staticMetaObject;
+ staticMetacallFunction = 0;
+ }
+
+ QByteArray className;
+ const QMetaObject *superClass;
+ QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction;
+ QList<QMetaMethodBuilderPrivate> methods;
+ QList<QMetaMethodBuilderPrivate> constructors;
+ QList<QMetaPropertyBuilderPrivate> properties;
+ QList<QByteArray> classInfoNames;
+ QList<QByteArray> classInfoValues;
+ QList<QMetaEnumBuilderPrivate> enumerators;
+ QList<const QMetaObject *> relatedMetaObjects;
+ int flags;
+};
+
+/*!
+ Constructs a new QMetaObjectBuilder.
+*/
+QMetaObjectBuilder::QMetaObjectBuilder()
+{
+ d = new QMetaObjectBuilderPrivate();
+}
+
+/*!
+ Constructs a new QMetaObjectBuilder which is a copy of the
+ meta object information in \a prototype. Note: the super class
+ contents for \a prototype are not copied, only the immediate
+ class that is defined by \a prototype.
+
+ The \a members parameter indicates which members of \a prototype
+ should be added. The default is AllMembers.
+
+ \sa addMetaObject()
+*/
+QMetaObjectBuilder::QMetaObjectBuilder
+ (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+{
+ d = new QMetaObjectBuilderPrivate();
+ addMetaObject(prototype, members);
+}
+
+/*!
+ Destroys this meta object builder.
+*/
+QMetaObjectBuilder::~QMetaObjectBuilder()
+{
+ delete d;
+}
+
+/*!
+ Returns the name of the class being constructed by this
+ meta object builder. The default value is an empty QByteArray.
+
+ \sa setClassName(), superClass()
+*/
+QByteArray QMetaObjectBuilder::className() const
+{
+ return d->className;
+}
+
+/*!
+ Sets the \a name of the class being constructed by this
+ meta object builder.
+
+ \sa className(), setSuperClass()
+*/
+void QMetaObjectBuilder::setClassName(const QByteArray& name)
+{
+ d->className = name;
+}
+
+/*!
+ Returns the superclass meta object of the class being constructed
+ by this meta object builder. The default value is the meta object
+ for QObject.
+
+ \sa setSuperClass(), className()
+*/
+const QMetaObject *QMetaObjectBuilder::superClass() const
+{
+ return d->superClass;
+}
+
+/*!
+ Sets the superclass meta object of the class being constructed
+ by this meta object builder to \a meta. The \a meta parameter
+ must not be null.
+
+ \sa superClass(), setClassName()
+*/
+void QMetaObjectBuilder::setSuperClass(const QMetaObject *meta)
+{
+ Q_ASSERT(meta);
+ d->superClass = meta;
+}
+
+/*!
+ Returns the flags of the class being constructed by this meta object
+ builder.
+
+ \sa setFlags()
+*/
+QMetaObjectBuilder::MetaObjectFlags QMetaObjectBuilder::flags() const
+{
+ return (QMetaObjectBuilder::MetaObjectFlags)d->flags;
+}
+
+/*!
+ Sets the \a flags of the class being constructed by this meta object
+ builder.
+
+ \sa flags()
+*/
+void QMetaObjectBuilder::setFlags(MetaObjectFlags flags)
+{
+ d->flags = flags;
+}
+
+/*!
+ Returns the number of methods in this class, excluding the number
+ of methods in the base class. These include signals and slots
+ as well as normal member functions.
+
+ \sa addMethod(), method(), removeMethod(), indexOfMethod()
+*/
+int QMetaObjectBuilder::methodCount() const
+{
+ return d->methods.size();
+}
+
+/*!
+ Returns the number of constructors in this class.
+
+ \sa addConstructor(), constructor(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+int QMetaObjectBuilder::constructorCount() const
+{
+ return d->constructors.size();
+}
+
+/*!
+ Returns the number of properties in this class, excluding the number
+ of properties in the base class.
+
+ \sa addProperty(), property(), removeProperty(), indexOfProperty()
+*/
+int QMetaObjectBuilder::propertyCount() const
+{
+ return d->properties.size();
+}
+
+/*!
+ Returns the number of enumerators in this class, excluding the
+ number of enumerators in the base class.
+
+ \sa addEnumerator(), enumerator(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+int QMetaObjectBuilder::enumeratorCount() const
+{
+ return d->enumerators.size();
+}
+
+/*!
+ Returns the number of items of class information in this class,
+ exclusing the number of items of class information in the base class.
+
+ \sa addClassInfo(), classInfoName(), classInfoValue()
+ \sa removeClassInfo(), indexOfClassInfo()
+*/
+int QMetaObjectBuilder::classInfoCount() const
+{
+ return d->classInfoNames.size();
+}
+
+/*!
+ Returns the number of related meta objects that are associated
+ with this class.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa addRelatedMetaObject(), relatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+int QMetaObjectBuilder::relatedMetaObjectCount() const
+{
+ return d->relatedMetaObjects.size();
+}
+
+/*!
+ Adds a new public method to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the method. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Method, signature));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new public method to this class with the specified
+ \a signature and \a returnType. Returns an object that can be
+ used to adjust the other attributes of the method. The \a signature
+ and \a returnType will be normalized before they are added to
+ the class. If \a returnType is empty, then it indicates that
+ the method has \c{void} as its return type.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod
+ (const QByteArray& signature, const QByteArray& returnType)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate
+ (QMetaMethod::Method, signature, returnType));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new public method to this class that has the same information as
+ \a prototype. This is used to clone the methods of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the method.
+
+ This function will detect if \a prototype is an ordinary method,
+ signal, slot, or constructor and act accordingly.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
+{
+ QMetaMethodBuilder method;
+ if (prototype.methodType() == QMetaMethod::Method)
+ method = addMethod(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Signal)
+ method = addSignal(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Slot)
+ method = addSlot(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Constructor)
+ method = addConstructor(prototype.signature());
+ method.setReturnType(prototype.typeName());
+ method.setParameterNames(prototype.parameterNames());
+ method.setTag(prototype.tag());
+ method.setAccess(prototype.access());
+ method.setAttributes(prototype.attributes());
+ return method;
+}
+
+/*!
+ Adds a new public slot to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the slot. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa addMethod(), addSignal(), indexOfSlot()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Slot, signature));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new signal to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the signal. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa addMethod(), addSlot(), indexOfSignal()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate
+ (QMetaMethod::Signal, signature, QByteArray(), QMetaMethod::Protected));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new constructor to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the constructor. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa constructor(), constructorCount(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signature)
+{
+ int index = d->constructors.size();
+ d->constructors.append(QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature));
+ return QMetaMethodBuilder(this, -(index + 1));
+}
+
+/*!
+ Adds a new constructor to this class that has the same information as
+ \a prototype. This is used to clone the constructors of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the constructor.
+
+ This function requires that \a prototype be a constructor.
+
+ \sa constructor(), constructorCount(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototype)
+{
+ Q_ASSERT(prototype.methodType() == QMetaMethod::Constructor);
+ QMetaMethodBuilder ctor = addConstructor(prototype.signature());
+ ctor.setReturnType(prototype.typeName());
+ ctor.setParameterNames(prototype.parameterNames());
+ ctor.setTag(prototype.tag());
+ ctor.setAccess(prototype.access());
+ ctor.setAttributes(prototype.attributes());
+ return ctor;
+}
+
+/*!
+ Adds a new readable/writable property to this class with the
+ specified \a name and \a type. Returns an object that can be used
+ to adjust the other attributes of the property. The \a type will
+ be normalized before it is added to the class. \a notifierId will
+ be registered as the property\s \e notify signal.
+
+ \sa property(), propertyCount(), removeProperty(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty
+ (const QByteArray& name, const QByteArray& type, int notifierId)
+{
+ int index = d->properties.size();
+ d->properties.append(QMetaPropertyBuilderPrivate(name, type, notifierId));
+ return QMetaPropertyBuilder(this, index);
+}
+
+/*!
+ Adds a new property to this class that has the same information as
+ \a prototype. This is used to clone the properties of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the property.
+
+ \sa property(), propertyCount(), removeProperty(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& prototype)
+{
+ QMetaPropertyBuilder property = addProperty(prototype.name(), prototype.typeName());
+ property.setReadable(prototype.isReadable());
+ property.setWritable(prototype.isWritable());
+ property.setResettable(prototype.isResettable());
+ property.setDesignable(prototype.isDesignable());
+ property.setScriptable(prototype.isScriptable());
+ property.setStored(prototype.isStored());
+ property.setEditable(prototype.isEditable());
+ property.setUser(prototype.isUser());
+ property.setStdCppSet(prototype.hasStdCppSet());
+ property.setEnumOrFlag(prototype.isEnumType());
+ if (prototype.hasNotifySignal()) {
+ // Find an existing method for the notify signal, or add a new one.
+ QMetaMethod method = prototype.notifySignal();
+ int index = indexOfMethod(method.signature());
+ if (index == -1)
+ index = addMethod(method).index();
+ d->properties[property._index].notifySignal = index;
+ d->properties[property._index].setFlag(Notify, true);
+ }
+ return property;
+}
+
+/*!
+ Adds a new enumerator to this class with the specified
+ \a name. Returns an object that can be used to adjust
+ the other attributes of the enumerator.
+
+ \sa enumerator(), enumeratorCount(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name)
+{
+ int index = d->enumerators.size();
+ d->enumerators.append(QMetaEnumBuilderPrivate(name));
+ return QMetaEnumBuilder(this, index);
+}
+
+/*!
+ Adds a new enumerator to this class that has the same information as
+ \a prototype. This is used to clone the enumerators of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the enumerator.
+
+ \sa enumerator(), enumeratorCount(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
+{
+ QMetaEnumBuilder en = addEnumerator(prototype.name());
+ en.setIsFlag(prototype.isFlag());
+ int count = prototype.keyCount();
+ for (int index = 0; index < count; ++index)
+ en.addKey(prototype.key(index), prototype.value(index));
+ return en;
+}
+
+/*!
+ Adds \a name and \a value as an item of class information to this class.
+ Returns the index of the new item of class information.
+
+ \sa classInfoCount(), classInfoName(), classInfoValue()
+ \sa removeClassInfo(), indexOfClassInfo()
+*/
+int QMetaObjectBuilder::addClassInfo(const QByteArray& name, const QByteArray& value)
+{
+ int index = d->classInfoNames.size();
+ d->classInfoNames += name;
+ d->classInfoValues += value;
+ return index;
+}
+
+/*!
+ Adds \a meta to this class as a related meta object. Returns
+ the index of the new related meta object entry.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), relatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+int QMetaObjectBuilder::addRelatedMetaObject(const QMetaObject *meta)
+{
+ Q_ASSERT(meta);
+ int index = d->relatedMetaObjects.size();
+ d->relatedMetaObjects.append(meta);
+ return index;
+}
+
+/*!
+ Adds the contents of \a prototype to this meta object builder.
+ This function is useful for cloning the contents of an existing QMetaObject.
+
+ The \a members parameter indicates which members of \a prototype
+ should be added. The default is AllMembers.
+*/
+void QMetaObjectBuilder::addMetaObject
+ (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+{
+ Q_ASSERT(prototype);
+ int index;
+
+ if ((members & ClassName) != 0)
+ d->className = prototype->className();
+
+ if ((members & SuperClass) != 0)
+ d->superClass = prototype->superClass();
+
+ if ((members & (Methods | Signals | Slots)) != 0) {
+ for (index = prototype->methodOffset(); index < prototype->methodCount(); ++index) {
+ QMetaMethod method = prototype->method(index);
+ if (method.methodType() != QMetaMethod::Signal) {
+ if (method.access() == QMetaMethod::Public && (members & PublicMethods) == 0)
+ continue;
+ if (method.access() == QMetaMethod::Private && (members & PrivateMethods) == 0)
+ continue;
+ if (method.access() == QMetaMethod::Protected && (members & ProtectedMethods) == 0)
+ continue;
+ }
+ if (method.methodType() == QMetaMethod::Method && (members & Methods) != 0) {
+ addMethod(method);
+ } else if (method.methodType() == QMetaMethod::Signal &&
+ (members & Signals) != 0) {
+ addMethod(method);
+ } else if (method.methodType() == QMetaMethod::Slot &&
+ (members & Slots) != 0) {
+ addMethod(method);
+ }
+ }
+ }
+
+ if ((members & Constructors) != 0) {
+ for (index = 0; index < prototype->constructorCount(); ++index)
+ addConstructor(prototype->constructor(index));
+ }
+
+ if ((members & Properties) != 0) {
+ for (index = prototype->propertyOffset(); index < prototype->propertyCount(); ++index)
+ addProperty(prototype->property(index));
+ }
+
+ if ((members & Enumerators) != 0) {
+ for (index = prototype->enumeratorOffset(); index < prototype->enumeratorCount(); ++index)
+ addEnumerator(prototype->enumerator(index));
+ }
+
+ if ((members & ClassInfos) != 0) {
+ for (index = prototype->classInfoOffset(); index < prototype->classInfoCount(); ++index) {
+ QMetaClassInfo ci = prototype->classInfo(index);
+ addClassInfo(ci.name(), ci.value());
+ }
+ }
+
+ if ((members & RelatedMetaObjects) != 0) {
+ const QMetaObject **objects;
+ if (priv(prototype->d.data)->revision < 2) {
+ objects = (const QMetaObject **)(prototype->d.extradata);
+ } else {
+ const QMetaObjectExtraData *extra = (const QMetaObjectExtraData *)(prototype->d.extradata);
+ if (extra)
+ objects = extra->objects;
+ else
+ objects = 0;
+ }
+ if (objects) {
+ while (*objects != 0) {
+ addRelatedMetaObject(*objects);
+ ++objects;
+ }
+ }
+ }
+
+ if ((members & StaticMetacall) != 0) {
+ if (priv(prototype->d.data)->revision >= 2) {
+ const QMetaObjectExtraData *extra =
+ (const QMetaObjectExtraData *)(prototype->d.extradata);
+ if (extra && extra->static_metacall)
+ setStaticMetacallFunction(extra->static_metacall);
+ }
+ }
+}
+
+/*!
+ Returns the method at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::method(int index) const
+{
+ if (index >= 0 && index < d->methods.size())
+ return QMetaMethodBuilder(this, index);
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Returns the constructor at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::constructor(int index) const
+{
+ if (index >= 0 && index < d->constructors.size())
+ return QMetaMethodBuilder(this, -(index + 1));
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Returns the property at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::property(int index) const
+{
+ if (index >= 0 && index < d->properties.size())
+ return QMetaPropertyBuilder(this, index);
+ else
+ return QMetaPropertyBuilder();
+}
+
+/*!
+ Returns the enumerator at \a index in this class.
+
+ \sa enumeratorCount(), addEnumerator(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::enumerator(int index) const
+{
+ if (index >= 0 && index < d->enumerators.size())
+ return QMetaEnumBuilder(this, index);
+ else
+ return QMetaEnumBuilder();
+}
+
+/*!
+ Returns the related meta object at \a index in this class.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), addRelatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+const QMetaObject *QMetaObjectBuilder::relatedMetaObject(int index) const
+{
+ if (index >= 0 && index < d->relatedMetaObjects.size())
+ return d->relatedMetaObjects[index];
+ else
+ return 0;
+}
+
+/*!
+ Returns the name of the item of class information at \a index
+ in this class.
+
+ \sa classInfoCount(), addClassInfo(), classInfoValue()
+ \sa removeClassInfo(), indexOfClassInfo()
+*/
+QByteArray QMetaObjectBuilder::classInfoName(int index) const
+{
+ if (index >= 0 && index < d->classInfoNames.size())
+ return d->classInfoNames[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the value of the item of class information at \a index
+ in this class.
+
+ \sa classInfoCount(), addClassInfo(), classInfoName()
+ \sa removeClassInfo(), indexOfClassInfo()
+*/
+QByteArray QMetaObjectBuilder::classInfoValue(int index) const
+{
+ if (index >= 0 && index < d->classInfoValues.size())
+ return d->classInfoValues[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Removes the method at \a index from this class. The indices of
+ all following methods will be adjusted downwards by 1. If the
+ method is registered as a notify signal on a property, then the
+ notify signal will be removed from the property.
+
+ \sa methodCount(), addMethod(), method(), indexOfMethod()
+*/
+void QMetaObjectBuilder::removeMethod(int index)
+{
+ if (index >= 0 && index < d->methods.size()) {
+ d->methods.removeAt(index);
+ for (int prop = 0; prop < d->properties.size(); ++prop) {
+ // Adjust the indices of property notify signal references.
+ if (d->properties[prop].notifySignal == index)
+ d->properties[prop].notifySignal = -1;
+ else if (d->properties[prop].notifySignal > index)
+ (d->properties[prop].notifySignal)--;
+ }
+ }
+}
+
+/*!
+ Removes the constructor at \a index from this class. The indices of
+ all following constructors will be adjusted downwards by 1.
+
+ \sa constructorCount(), addConstructor(), constructor()
+ \sa indexOfConstructor()
+*/
+void QMetaObjectBuilder::removeConstructor(int index)
+{
+ if (index >= 0 && index < d->constructors.size())
+ d->constructors.removeAt(index);
+}
+
+/*!
+ Removes the property at \a index from this class. The indices of
+ all following properties will be adjusted downwards by 1.
+
+ \sa propertyCount(), addProperty(), property(), indexOfProperty()
+*/
+void QMetaObjectBuilder::removeProperty(int index)
+{
+ if (index >= 0 && index < d->properties.size())
+ d->properties.removeAt(index);
+}
+
+/*!
+ Removes the enumerator at \a index from this class. The indices of
+ all following enumerators will be adjusted downwards by 1.
+
+ \sa enumeratorCount(), addEnumerator(), enumerator()
+ \sa indexOfEnumerator()
+*/
+void QMetaObjectBuilder::removeEnumerator(int index)
+{
+ if (index >= 0 && index < d->enumerators.size())
+ d->enumerators.removeAt(index);
+}
+
+/*!
+ Removes the item of class information at \a index from this class.
+ The indices of all following items will be adjusted downwards by 1.
+
+ \sa classInfoCount(), addClassInfo(), classInfoName()
+ \sa classInfoValue() indexOfClassInfo()
+*/
+void QMetaObjectBuilder::removeClassInfo(int index)
+{
+ if (index >= 0 && index < d->classInfoNames.size()) {
+ d->classInfoNames.removeAt(index);
+ d->classInfoValues.removeAt(index);
+ }
+}
+
+/*!
+ Removes the related meta object at \a index from this class.
+ The indices of all following related meta objects will be adjusted
+ downwards by 1.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), addRelatedMetaObject()
+ \sa relatedMetaObject()
+*/
+void QMetaObjectBuilder::removeRelatedMetaObject(int index)
+{
+ if (index >= 0 && index < d->relatedMetaObjects.size())
+ d->relatedMetaObjects.removeAt(index);
+}
+
+/*!
+ Finds a method with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa method(), methodCount(), addMethod(), removeMethod()
+*/
+int QMetaObjectBuilder::indexOfMethod(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a signal with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa indexOfMethod(), indexOfSlot()
+*/
+int QMetaObjectBuilder::indexOfSignal(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature &&
+ d->methods[index].methodType() == QMetaMethod::Signal)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a slot with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa indexOfMethod(), indexOfSignal()
+*/
+int QMetaObjectBuilder::indexOfSlot(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature &&
+ d->methods[index].methodType() == QMetaMethod::Slot)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a constructor with the specified \a signature and returns its
+ index; otherwise returns -1. The \a signature will be normalized by
+ this method.
+
+ \sa constructor(), constructorCount(), addConstructor()
+ \sa removeConstructor()
+*/
+int QMetaObjectBuilder::indexOfConstructor(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->constructors.size(); ++index) {
+ if (sig == d->constructors[index].signature)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a property with the specified \a name and returns its index;
+ otherwise returns -1.
+
+ \sa property(), propertyCount(), addProperty(), removeProperty()
+*/
+int QMetaObjectBuilder::indexOfProperty(const QByteArray& name)
+{
+ for (int index = 0; index < d->properties.size(); ++index) {
+ if (name == d->properties[index].name)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds an enumerator with the specified \a name and returns its index;
+ otherwise returns -1.
+
+ \sa enumerator(), enumeratorCount(), addEnumerator()
+ \sa removeEnumerator()
+*/
+int QMetaObjectBuilder::indexOfEnumerator(const QByteArray& name)
+{
+ for (int index = 0; index < d->enumerators.size(); ++index) {
+ if (name == d->enumerators[index].name)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds an item of class information with the specified \a name and
+ returns its index; otherwise returns -1.
+
+ \sa classInfoName(), classInfoValue(), classInfoCount(), addClassInfo()
+ \sa removeClassInfo()
+*/
+int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
+{
+ for (int index = 0; index < d->classInfoNames.size(); ++index) {
+ if (name == d->classInfoNames[index])
+ return index;
+ }
+ return -1;
+}
+
+// Align on a specific type boundary.
+#define ALIGN(size,type) \
+ (size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
+
+// Build a string into a QMetaObject representation. Returns the
+// position in the string table where the string was placed.
+static int buildString
+ (char *buf, char *str, int *offset, const QByteArray& value, int empty)
+{
+ if (value.size() == 0 && empty >= 0)
+ return empty;
+ if (buf) {
+ memcpy(str + *offset, value.constData(), value.size());
+ str[*offset + value.size()] = '\0';
+ }
+ int posn = *offset;
+ *offset += value.size() + 1;
+ return posn;
+}
+
+// Build the parameter array string for a method.
+static QByteArray buildParameterNames
+ (const QByteArray& signature, const QList<QByteArray>& parameterNames)
+{
+ // If the parameter name list is specified, then concatenate them.
+ if (!parameterNames.isEmpty()) {
+ QByteArray names;
+ bool first = true;
+ foreach (QByteArray name, parameterNames) {
+ if (first)
+ first = false;
+ else
+ names += (char)',';
+ names += name;
+ }
+ return names;
+ }
+
+ // Count commas in the signature, excluding those inside template arguments.
+ int index = signature.indexOf('(');
+ if (index < 0)
+ return QByteArray();
+ ++index;
+ if (index >= signature.size())
+ return QByteArray();
+ if (signature[index] == ')')
+ return QByteArray();
+ int count = 1;
+ int brackets = 0;
+ while (index < signature.size() && signature[index] != ',') {
+ char ch = signature[index++];
+ if (ch == '<')
+ ++brackets;
+ else if (ch == '>')
+ --brackets;
+ else if (ch == ',' && brackets <= 0)
+ ++count;
+ }
+ return QByteArray(count - 1, ',');
+}
+
+// Build a QMetaObject in "buf" based on the information in "d".
+// If "buf" is null, then return the number of bytes needed to
+// build the QMetaObject.
+static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf)
+{
+ int size = 0;
+ int dataIndex;
+ int enumIndex;
+ int index;
+ bool hasNotifySignals = false;
+
+ // Create the main QMetaObject structure at the start of the buffer.
+ QMetaObject *meta = reinterpret_cast<QMetaObject *>(buf);
+ size += sizeof(QMetaObject);
+ ALIGN(size, int);
+ if (buf) {
+ meta->d.superdata = d->superClass;
+ meta->d.extradata = 0;
+ }
+
+ // Populate the QMetaObjectPrivate structure.
+ QMetaObjectPrivate *pmeta
+ = reinterpret_cast<QMetaObjectPrivate *>(buf + size);
+ dataIndex = 13; // Number of fields in the QMetaObjectPrivate.
+ for (index = 0; index < d->properties.size(); ++index) {
+ if (d->properties[index].notifySignal != -1) {
+ hasNotifySignals = true;
+ break;
+ }
+ }
+ if (buf) {
+ pmeta->revision = 3;
+ pmeta->flags = d->flags;
+ pmeta->className = 0; // Class name is always the first string.
+
+ pmeta->classInfoCount = d->classInfoNames.size();
+ pmeta->classInfoData = dataIndex;
+ dataIndex += 2 * d->classInfoNames.size();
+
+ pmeta->methodCount = d->methods.size();
+ pmeta->methodData = dataIndex;
+ dataIndex += 5 * d->methods.size();
+
+ pmeta->propertyCount = d->properties.size();
+ pmeta->propertyData = dataIndex;
+ dataIndex += 3 * d->properties.size();
+ if (hasNotifySignals)
+ dataIndex += d->properties.size();
+
+ pmeta->enumeratorCount = d->enumerators.size();
+ pmeta->enumeratorData = dataIndex;
+ dataIndex += 4 * d->enumerators.size();
+
+ pmeta->constructorCount = d->constructors.size();
+ pmeta->constructorData = dataIndex;
+ dataIndex += 5 * d->constructors.size();
+ } else {
+ dataIndex += 2 * d->classInfoNames.size();
+ dataIndex += 5 * d->methods.size();
+ dataIndex += 3 * d->properties.size();
+ if (hasNotifySignals)
+ dataIndex += d->properties.size();
+ dataIndex += 4 * d->enumerators.size();
+ dataIndex += 5 * d->constructors.size();
+ }
+
+ // Allocate space for the enumerator key names and values.
+ enumIndex = dataIndex;
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ dataIndex += 2 * enumerator->keys.size();
+ }
+
+ // Zero terminator at the end of the data offset table.
+ ++dataIndex;
+
+ // Find the start of the data and string tables.
+ int *data = reinterpret_cast<int *>(pmeta);
+ size += dataIndex * sizeof(int);
+ char *str = reinterpret_cast<char *>(buf + size);
+ if (buf) {
+ meta->d.stringdata = str;
+ meta->d.data = reinterpret_cast<uint *>(data);
+ }
+
+ // Reset the current data position to just past the QMetaObjectPrivate.
+ dataIndex = 13;
+
+ // Add the class name to the string table.
+ int offset = 0;
+ buildString(buf, str, &offset, d->className, -1);
+
+ // Add a common empty string, which is used to indicate "void"
+ // method returns, empty tag strings, etc.
+ int empty = buildString(buf, str, &offset, QByteArray(), -1);
+
+ // Output the class infos,
+ for (index = 0; index < d->classInfoNames.size(); ++index) {
+ int name = buildString(buf, str, &offset, d->classInfoNames[index], empty);
+ int value = buildString(buf, str, &offset, d->classInfoValues[index], empty);
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = value;
+ }
+ dataIndex += 2;
+ }
+
+ // Output the methods in the class.
+ for (index = 0; index < d->methods.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ int sig = buildString(buf, str, &offset, method->signature, empty);
+ int params;
+ QByteArray names = buildParameterNames
+ (method->signature, method->parameterNames);
+ params = buildString(buf, str, &offset, names, empty);
+ int ret = buildString(buf, str, &offset, method->returnType, empty);
+ int tag = buildString(buf, str, &offset, method->tag, empty);
+ int attrs = method->attributes;
+ if (buf) {
+ data[dataIndex] = sig;
+ data[dataIndex + 1] = params;
+ data[dataIndex + 2] = ret;
+ data[dataIndex + 3] = tag;
+ data[dataIndex + 4] = attrs;
+ }
+ dataIndex += 5;
+ }
+
+ // Output the properties in the class.
+ for (index = 0; index < d->properties.size(); ++index) {
+ QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+ int name = buildString(buf, str, &offset, prop->name, empty);
+ int type = buildString(buf, str, &offset, prop->type, empty);
+ int flags = prop->flags;
+
+ if (!isVariantType(prop->type)) {
+ flags |= EnumOrFlag;
+ } else {
+ flags |= qvariant_nameToType(prop->type) << 24;
+ }
+
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = type;
+ data[dataIndex + 2] = flags;
+ }
+ dataIndex += 3;
+ }
+ if (hasNotifySignals) {
+ for (index = 0; index < d->properties.size(); ++index) {
+ QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+ if (buf) {
+ if (prop->notifySignal != -1)
+ data[dataIndex] = prop->notifySignal;
+ else
+ data[dataIndex] = 0;
+ }
+ ++dataIndex;
+ }
+ }
+
+ // Output the enumerators in the class.
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ int name = buildString(buf, str, &offset, enumerator->name, empty);
+ int isFlag = (int)(enumerator->isFlag);
+ int count = enumerator->keys.size();
+ int enumOffset = enumIndex;
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = isFlag;
+ data[dataIndex + 2] = count;
+ data[dataIndex + 3] = enumOffset;
+ }
+ for (int key = 0; key < count; ++key) {
+ int keyIndex = buildString(buf, str, &offset, enumerator->keys[key], empty);
+ if (buf) {
+ data[enumOffset++] = keyIndex;
+ data[enumOffset++] = enumerator->values[key];
+ }
+ }
+ dataIndex += 4;
+ enumIndex += 2 * count;
+ }
+
+ // Output the constructors in the class.
+ for (index = 0; index < d->constructors.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ int sig = buildString(buf, str, &offset, method->signature, empty);
+ int params;
+ QByteArray names = buildParameterNames
+ (method->signature, method->parameterNames);
+ params = buildString(buf, str, &offset, names, empty);
+ int ret = buildString(buf, str, &offset, method->returnType, empty);
+ int tag = buildString(buf, str, &offset, method->tag, empty);
+ int attrs = method->attributes;
+ if (buf) {
+ data[dataIndex] = sig;
+ data[dataIndex + 1] = params;
+ data[dataIndex + 2] = ret;
+ data[dataIndex + 3] = tag;
+ data[dataIndex + 4] = attrs;
+ }
+ dataIndex += 5;
+ }
+
+ // One more empty string to act as a terminator.
+ buildString(buf, str, &offset, QByteArray(), -1);
+ size += offset;
+
+ // Output the zero terminator in the data array.
+ if (buf)
+ data[enumIndex] = 0;
+
+ // Create the extradata block if we need one.
+ if (d->relatedMetaObjects.size() > 0 || d->staticMetacallFunction) {
+ ALIGN(size, QMetaObject **);
+ ALIGN(size, QMetaObjectBuilder::StaticMetacallFunction);
+ QMetaObjectExtraData *extra =
+ reinterpret_cast<QMetaObjectExtraData *>(buf + size);
+ size += sizeof(QMetaObjectExtraData);
+ ALIGN(size, QMetaObject *);
+ const QMetaObject **objects =
+ reinterpret_cast<const QMetaObject **>(buf + size);
+ if (buf) {
+ if (d->relatedMetaObjects.size() > 0) {
+ extra->objects = objects;
+ for (index = 0; index < d->relatedMetaObjects.size(); ++index)
+ objects[index] = d->relatedMetaObjects[index];
+ objects[index] = 0;
+ } else {
+ extra->objects = 0;
+ }
+ extra->static_metacall = d->staticMetacallFunction;
+ meta->d.extradata = reinterpret_cast<void *>(extra);
+ }
+ if (d->relatedMetaObjects.size() > 0)
+ size += sizeof(QMetaObject *) * (d->relatedMetaObjects.size() + 1);
+ }
+
+ // Align the final size and return it.
+ ALIGN(size, void *);
+ return size;
+}
+
+/*!
+ Converts this meta object builder into a concrete QMetaObject.
+ The return value should be deallocated using qFree() once it
+ is no longer needed.
+
+ The returned meta object is a snapshot of the state of the
+ QMetaObjectBuilder. Any further modifications to the QMetaObjectBuilder
+ will not be reflected in previous meta objects returned by
+ this method.
+*/
+QMetaObject *QMetaObjectBuilder::toMetaObject() const
+{
+ int size = buildMetaObject(d, 0);
+ char *buf = reinterpret_cast<char *>(qMalloc(size));
+ buildMetaObject(d, buf);
+ return reinterpret_cast<QMetaObject *>(buf);
+}
+
+/*!
+ \typedef QMetaObjectBuilder::StaticMetacallFunction
+
+ Typedef for static metacall functions. The three parameters are
+ the call type value, the constructor index, and the
+ array of parameters.
+*/
+
+/*!
+ Returns the static metacall function to use to construct objects
+ of this class. The default value is null.
+
+ \sa setStaticMetacallFunction()
+*/
+QMetaObjectBuilder::StaticMetacallFunction QMetaObjectBuilder::staticMetacallFunction() const
+{
+ return d->staticMetacallFunction;
+}
+
+/*!
+ Sets the static metacall function to use to construct objects
+ of this class to \a value. The default value is null.
+
+ \sa staticMetacallFunction()
+*/
+void QMetaObjectBuilder::setStaticMetacallFunction
+ (QMetaObjectBuilder::StaticMetacallFunction value)
+{
+ d->staticMetacallFunction = value;
+}
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+ Serializes the contents of the meta object builder onto \a stream.
+
+ \sa deserialize()
+*/
+void QMetaObjectBuilder::serialize(QDataStream& stream) const
+{
+ int index;
+
+ // Write the class and super class names.
+ stream << d->className;
+ if (d->superClass)
+ stream << QByteArray(d->superClass->className());
+ else
+ stream << QByteArray();
+
+ // Write the counts for each type of class member.
+ stream << d->classInfoNames.size();
+ stream << d->methods.size();
+ stream << d->properties.size();
+ stream << d->enumerators.size();
+ stream << d->constructors.size();
+ stream << d->relatedMetaObjects.size();
+
+ // Write the items of class information.
+ for (index = 0; index < d->classInfoNames.size(); ++index) {
+ stream << d->classInfoNames[index];
+ stream << d->classInfoValues[index];
+ }
+
+ // Write the methods.
+ for (index = 0; index < d->methods.size(); ++index) {
+ const QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ stream << method->signature;
+ stream << method->returnType;
+ stream << method->parameterNames;
+ stream << method->tag;
+ stream << method->attributes;
+ }
+
+ // Write the properties.
+ for (index = 0; index < d->properties.size(); ++index) {
+ const QMetaPropertyBuilderPrivate *property = &(d->properties[index]);
+ stream << property->name;
+ stream << property->type;
+ stream << property->flags;
+ stream << property->notifySignal;
+ }
+
+ // Write the enumerators.
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ const QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ stream << enumerator->name;
+ stream << enumerator->isFlag;
+ stream << enumerator->keys;
+ stream << enumerator->values;
+ }
+
+ // Write the constructors.
+ for (index = 0; index < d->constructors.size(); ++index) {
+ const QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ stream << method->signature;
+ stream << method->returnType;
+ stream << method->parameterNames;
+ stream << method->tag;
+ stream << method->attributes;
+ }
+
+ // Write the related meta objects.
+ for (index = 0; index < d->relatedMetaObjects.size(); ++index) {
+ const QMetaObject *meta = d->relatedMetaObjects[index];
+ stream << QByteArray(meta->className());
+ }
+
+ // Add an extra empty QByteArray for additional data in future versions.
+ // This should help maintain backwards compatibility, allowing older
+ // versions to read newer data.
+ stream << QByteArray();
+}
+
+// Resolve a class name using the name reference map.
+static const QMetaObject *resolveClassName
+ (const QMap<QByteArray, const QMetaObject *>& references,
+ const QByteArray& name)
+{
+ if (name == QByteArray("QObject"))
+ return &QObject::staticMetaObject;
+ else
+ return references.value(name, 0);
+}
+
+/*!
+ Deserializes a meta object builder from \a stream into
+ this meta object builder.
+
+ The \a references parameter specifies a mapping from class names
+ to QMetaObject instances for resolving the super class name and
+ related meta objects in the object that is deserialized.
+ The meta object for QObject is implicitly added to \a references
+ and does not need to be supplied.
+
+ The QDataStream::status() value on \a stream will be set to
+ QDataStream::ReadCorruptData if the input data is corrupt.
+ The status will be set to QDataStream::ReadPastEnd if the
+ input was exhausted before the full meta object was read.
+
+ \sa serialize()
+*/
+void QMetaObjectBuilder::deserialize
+ (QDataStream& stream,
+ const QMap<QByteArray, const QMetaObject *>& references)
+{
+ QByteArray name;
+ const QMetaObject *cl;
+ int index;
+
+ // Clear all members in the builder to their default states.
+ d->className.clear();
+ d->superClass = &QObject::staticMetaObject;
+ d->classInfoNames.clear();
+ d->classInfoValues.clear();
+ d->methods.clear();
+ d->properties.clear();
+ d->enumerators.clear();
+ d->constructors.clear();
+ d->relatedMetaObjects.clear();
+ d->staticMetacallFunction = 0;
+
+ // Read the class and super class names.
+ stream >> d->className;
+ stream >> name;
+ if (name.isEmpty()) {
+ d->superClass = 0;
+ } else if ((cl = resolveClassName(references, name)) != 0) {
+ d->superClass = cl;
+ } else {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+
+ // Read the counts for each type of class member.
+ int classInfoCount, methodCount, propertyCount;
+ int enumeratorCount, constructorCount, relatedMetaObjectCount;
+ stream >> classInfoCount;
+ stream >> methodCount;
+ stream >> propertyCount;
+ stream >> enumeratorCount;
+ stream >> constructorCount;
+ stream >> relatedMetaObjectCount;
+ if (classInfoCount < 0 || methodCount < 0 ||
+ propertyCount < 0 || enumeratorCount < 0 ||
+ constructorCount < 0 || relatedMetaObjectCount < 0) {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+
+ // Read the items of class information.
+ for (index = 0; index < classInfoCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ QByteArray value;
+ stream >> name;
+ stream >> value;
+ addClassInfo(name, value);
+ }
+
+ // Read the member methods.
+ for (index = 0; index < methodCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addMethod(name);
+ QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ stream >> method->returnType;
+ stream >> method->parameterNames;
+ stream >> method->tag;
+ stream >> method->attributes;
+ if (method->methodType() == QMetaMethod::Constructor) {
+ // Cannot add a constructor in this set of methods.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the properties.
+ for (index = 0; index < propertyCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ QByteArray type;
+ stream >> name;
+ stream >> type;
+ addProperty(name, type);
+ QMetaPropertyBuilderPrivate *property = &(d->properties[index]);
+ stream >> property->flags;
+ stream >> property->notifySignal;
+ if (property->notifySignal < -1 ||
+ property->notifySignal >= d->methods.size()) {
+ // Notify signal method index is out of range.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ if (property->notifySignal >= 0 &&
+ d->methods[property->notifySignal].methodType() != QMetaMethod::Signal) {
+ // Notify signal method index does not refer to a signal.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the enumerators.
+ for (index = 0; index < enumeratorCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addEnumerator(name);
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ stream >> enumerator->isFlag;
+ stream >> enumerator->keys;
+ stream >> enumerator->values;
+ if (enumerator->keys.size() != enumerator->values.size()) {
+ // Mismatch between number of keys and number of values.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the constructor methods.
+ for (index = 0; index < constructorCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addConstructor(name);
+ QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ stream >> method->returnType;
+ stream >> method->parameterNames;
+ stream >> method->tag;
+ stream >> method->attributes;
+ if (method->methodType() != QMetaMethod::Constructor) {
+ // The type must be Constructor.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the related meta objects.
+ for (index = 0; index < relatedMetaObjectCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ cl = resolveClassName(references, name);
+ if (!cl) {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ addRelatedMetaObject(cl);
+ }
+
+ // Read the extra data block, which is reserved for future use.
+ stream >> name;
+}
+
+#endif // !QT_NO_DATASTREAM
+
+/*!
+ \class QMetaMethodBuilder
+ \brief The QMetaMethodBuilder class enables modifications to a method definition on a meta object builder.
+*/
+
+QMetaMethodBuilderPrivate *QMetaMethodBuilder::d_func() const
+{
+ // Positive indices indicate methods, negative indices indicate constructors.
+ if (_mobj && _index >= 0 && _index < _mobj->d->methods.size())
+ return &(_mobj->d->methods[_index]);
+ else if (_mobj && -_index >= 1 && -_index <= _mobj->d->constructors.size())
+ return &(_mobj->d->constructors[(-_index) - 1]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaMethodBuilder::QMetaMethodBuilder()
+ \internal
+*/
+
+/*!
+ Returns the index of this method within its QMetaObjectBuilder.
+*/
+int QMetaMethodBuilder::index() const
+{
+ if (_index >= 0)
+ return _index; // Method, signal, or slot
+ else
+ return (-_index) - 1; // Constructor
+}
+
+/*!
+ Returns the type of this method (signal, slot, method, or constructor).
+*/
+QMetaMethod::MethodType QMetaMethodBuilder::methodType() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->methodType();
+ else
+ return QMetaMethod::Method;
+}
+
+/*!
+ Returns the signature of this method.
+
+ \sa parameterNames(), returnType()
+*/
+QByteArray QMetaMethodBuilder::signature() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->signature;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the return type for this method; empty if the method's
+ return type is \c{void}.
+
+ \sa setReturnType(), signature()
+*/
+QByteArray QMetaMethodBuilder::returnType() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->returnType;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets the return type for this method to \a value. If \a value
+ is empty, then the method's return type is \c{void}. The \a value
+ will be normalized before it is added to the method.
+
+ \sa returnType(), signature()
+*/
+void QMetaMethodBuilder::setReturnType(const QByteArray& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->returnType = QMetaObject::normalizedType(value);
+}
+
+/*!
+ Returns the list of parameter names for this method.
+
+ \sa setParameterNames()
+*/
+QList<QByteArray> QMetaMethodBuilder::parameterNames() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->parameterNames;
+ else
+ return QList<QByteArray>();
+}
+
+/*!
+ Sets the list of parameter names for this method to \a value.
+
+ \sa parameterNames()
+*/
+void QMetaMethodBuilder::setParameterNames(const QList<QByteArray>& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->parameterNames = value;
+}
+
+/*!
+ Returns the tag associated with this method.
+
+ \sa setTag()
+*/
+QByteArray QMetaMethodBuilder::tag() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->tag;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets the tag associated with this method to \a value.
+
+ \sa tag()
+*/
+void QMetaMethodBuilder::setTag(const QByteArray& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->tag = value;
+}
+
+/*!
+ Returns the access specification of this method (private, protected,
+ or public). The default value is QMetaMethod::Public for methods,
+ slots, and constructors. The default value is QMetaMethod::Protected
+ for signals.
+
+ \sa setAccess()
+*/
+QMetaMethod::Access QMetaMethodBuilder::access() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->access();
+ else
+ return QMetaMethod::Public;
+}
+
+/*!
+ Sets the access specification of this method (private, protected,
+ or public) to \a value. If the method is a signal, this function
+ will be ignored.
+
+ \sa access()
+*/
+void QMetaMethodBuilder::setAccess(QMetaMethod::Access value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d && d->methodType() != QMetaMethod::Signal)
+ d->setAccess(value);
+}
+
+/*!
+ Returns the additional attributes for this method.
+
+ \sa setAttributes()
+*/
+int QMetaMethodBuilder::attributes() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return (d->attributes >> 4);
+ else
+ return 0;
+}
+
+/*!
+ Sets the additional attributes for this method to \a value.
+
+ \sa attributes()
+*/
+void QMetaMethodBuilder::setAttributes(int value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->attributes = ((d->attributes & 0x0f) | (value << 4));
+}
+
+/*!
+ \class QMetaPropertyBuilder
+ \brief The QMetaPropertyBuilder class enables modifications to a property definition on a meta object builder.
+*/
+
+QMetaPropertyBuilderPrivate *QMetaPropertyBuilder::d_func() const
+{
+ if (_mobj && _index >= 0 && _index < _mobj->d->properties.size())
+ return &(_mobj->d->properties[_index]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaPropertyBuilder::QMetaPropertyBuilder()
+ \internal
+*/
+
+/*!
+ \fn int QMetaPropertyBuilder::index() const
+
+ Returns the index of this property within its QMetaObjectBuilder.
+*/
+
+/*!
+ Returns the name associated with this property.
+
+ \sa type()
+*/
+QByteArray QMetaPropertyBuilder::name() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the type associated with this property.
+
+ \sa name()
+*/
+QByteArray QMetaPropertyBuilder::type() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->type;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns true if this property has a notify signal; false otherwise.
+
+ \sa notifySignal(), setNotifySignal(), removeNotifySignal()
+*/
+bool QMetaPropertyBuilder::hasNotifySignal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Notify);
+ else
+ return false;
+}
+
+/*!
+ Returns the notify signal associated with this property.
+
+ \sa hasNotifySignal(), setNotifySignal(), removeNotifySignal()
+*/
+QMetaMethodBuilder QMetaPropertyBuilder::notifySignal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d && d->notifySignal >= 0)
+ return QMetaMethodBuilder(_mobj, d->notifySignal);
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Sets the notify signal associated with this property to \a value.
+
+ \sa hasNotifySignal(), notifySignal(), removeNotifySignal()
+*/
+void QMetaPropertyBuilder::setNotifySignal(const QMetaMethodBuilder& value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d) {
+ if (value._mobj) {
+ d->notifySignal = value._index;
+ d->setFlag(Notify, true);
+ } else {
+ d->notifySignal = -1;
+ d->setFlag(Notify, false);
+ }
+ }
+}
+
+/*!
+ Removes the notify signal from this property.
+
+ \sa hasNotifySignal(), notifySignal(), setNotifySignal()
+*/
+void QMetaPropertyBuilder::removeNotifySignal()
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d) {
+ d->notifySignal = -1;
+ d->setFlag(Notify, false);
+ }
+}
+
+/*!
+ Returns true if this property is readable; otherwise returns false.
+ The default value is true.
+
+ \sa setReadable(), isWritable()
+*/
+bool QMetaPropertyBuilder::isReadable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Readable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is writable; otherwise returns false.
+ The default value is true.
+
+ \sa setWritable(), isReadable()
+*/
+bool QMetaPropertyBuilder::isWritable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Writable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property can be reset to a default value; otherwise
+ returns false. The default value is false.
+
+ \sa setResettable()
+*/
+bool QMetaPropertyBuilder::isResettable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Resettable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is designable; otherwise returns false.
+ This default value is false.
+
+ \sa setDesignable(), isScriptable(), isStored()
+*/
+bool QMetaPropertyBuilder::isDesignable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Designable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is scriptable; otherwise returns false.
+ This default value is false.
+
+ \sa setScriptable(), isDesignable(), isStored()
+*/
+bool QMetaPropertyBuilder::isScriptable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Scriptable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is stored; otherwise returns false.
+ This default value is false.
+
+ \sa setStored(), isDesignable(), isScriptable()
+*/
+bool QMetaPropertyBuilder::isStored() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Stored);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is editable; otherwise returns false.
+ This default value is false.
+
+ \sa setEditable(), isDesignable(), isScriptable(), isStored()
+*/
+bool QMetaPropertyBuilder::isEditable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Editable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is designated as the \c USER
+ property, i.e., the one that the user can edit or that is
+ significant in some other way. Otherwise it returns
+ false. This default value is false.
+
+ \sa setUser(), isDesignable(), isScriptable()
+*/
+bool QMetaPropertyBuilder::isUser() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(User);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property has a C++ setter function that
+ follows Qt's standard "name" / "setName" pattern. Designer and uic
+ query hasStdCppSet() in order to avoid expensive
+ QObject::setProperty() calls. All properties in Qt [should] follow
+ this pattern. The default value is false.
+
+ \sa setStdCppSet()
+*/
+bool QMetaPropertyBuilder::hasStdCppSet() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(StdCppSet);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is an enumerator or flag type;
+ otherwise returns false. This default value is false.
+
+ \sa setEnumOrFlag()
+*/
+bool QMetaPropertyBuilder::isEnumOrFlag() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(EnumOrFlag);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property has the dynamic flag set;
+ otherwise returns false. The default value is false.
+
+ \sa setDynamic()
+*/
+bool QMetaPropertyBuilder::isDynamic() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Dynamic);
+ else
+ return false;
+}
+
+/*!
+ Sets this property to readable if \a value is true.
+
+ \sa isReadable(), setWritable()
+*/
+void QMetaPropertyBuilder::setReadable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Readable, value);
+}
+
+/*!
+ Sets this property to writable if \a value is true.
+
+ \sa isWritable(), setReadable()
+*/
+void QMetaPropertyBuilder::setWritable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Writable, value);
+}
+
+/*!
+ Sets this property to resettable if \a value is true.
+
+ \sa isResettable()
+*/
+void QMetaPropertyBuilder::setResettable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Resettable, value);
+}
+
+/*!
+ Sets this property to designable if \a value is true.
+
+ \sa isDesignable(), setScriptable(), setStored()
+*/
+void QMetaPropertyBuilder::setDesignable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Designable, value);
+}
+
+/*!
+ Sets this property to scriptable if \a value is true.
+
+ \sa isScriptable(), setDesignable(), setStored()
+*/
+void QMetaPropertyBuilder::setScriptable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Scriptable, value);
+}
+
+/*!
+ Sets this property to storable if \a value is true.
+
+ \sa isStored(), setDesignable(), setScriptable()
+*/
+void QMetaPropertyBuilder::setStored(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Stored, value);
+}
+
+/*!
+ Sets this property to editable if \a value is true.
+
+ \sa isEditable(), setDesignable(), setScriptable(), setStored()
+*/
+void QMetaPropertyBuilder::setEditable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Editable, value);
+}
+
+/*!
+ Sets the \c USER flag on this property to \a value.
+
+ \sa isUser(), setDesignable(), setScriptable()
+*/
+void QMetaPropertyBuilder::setUser(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(User, value);
+}
+
+/*!
+ Sets the C++ setter flag on this property to \a value, which is
+ true if the property has a C++ setter function that follows Qt's
+ standard "name" / "setName" pattern.
+
+ \sa hasStdCppSet()
+*/
+void QMetaPropertyBuilder::setStdCppSet(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(StdCppSet, value);
+}
+
+/*!
+ Sets this property to be of an enumerator or flag type if
+ \a value is true.
+
+ \sa isEnumOrFlag()
+*/
+void QMetaPropertyBuilder::setEnumOrFlag(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(EnumOrFlag, value);
+}
+
+/*!
+ Sets this property to have the dynamic flag if \a value is
+ true.
+
+ \sa isDynamic()
+*/
+void QMetaPropertyBuilder::setDynamic(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Dynamic, value);
+}
+
+/*!
+ \class QMetaEnumBuilder
+ \brief The QMetaEnumBuilder class enables modifications to an enumerator definition on a meta object builder.
+*/
+
+QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const
+{
+ if (_mobj && _index >= 0 && _index < _mobj->d->enumerators.size())
+ return &(_mobj->d->enumerators[_index]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaEnumBuilder::QMetaEnumBuilder()
+ \internal
+*/
+
+/*!
+ \fn int QMetaEnumBuilder::index() const
+
+ Returns the index of this enumerator within its QMetaObjectBuilder.
+*/
+
+/*!
+ Returns the name of the enumerator (without the scope).
+*/
+QByteArray QMetaEnumBuilder::name() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns true if this enumerator is used as a flag; otherwise returns
+ false.
+
+ \sa setIsFlag()
+*/
+bool QMetaEnumBuilder::isFlag() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->isFlag;
+ else
+ return false;
+}
+
+/*!
+ Sets this enumerator to be used as a flag if \a value is true.
+
+ \sa isFlag()
+*/
+void QMetaEnumBuilder::setIsFlag(bool value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ d->isFlag = value;
+}
+
+/*!
+ Returns the number of keys.
+
+ \sa key(), addKey()
+*/
+int QMetaEnumBuilder::keyCount() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->keys.size();
+ else
+ return 0;
+}
+
+/*!
+ Returns the key with the given \a index, or an empty QByteArray
+ if no such key exists.
+
+ \sa keyCount(), addKey(), value()
+*/
+QByteArray QMetaEnumBuilder::key(int index) const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size())
+ return d->keys[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the value with the given \a index; or returns -1 if there
+ is no such value.
+
+ \sa keyCount(), addKey(), key()
+*/
+int QMetaEnumBuilder::value(int index) const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size())
+ return d->values[index];
+ else
+ return -1;
+}
+
+/*!
+ Adds a new key called \a name to this enumerator, associated
+ with \a value. Returns the index of the new key.
+
+ \sa keyCount(), key(), value(), removeKey()
+*/
+int QMetaEnumBuilder::addKey(const QByteArray& name, int value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d) {
+ int index = d->keys.size();
+ d->keys += name;
+ d->values += value;
+ return index;
+ } else {
+ return -1;
+ }
+}
+
+/*!
+ Removes the key at \a index from this enumerator.
+
+ \sa addKey()
+*/
+void QMetaEnumBuilder::removeKey(int index)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size()) {
+ d->keys.removeAt(index);
+ d->values.removeAt(index);
+ }
+}
diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h
new file mode 100644
index 0000000..dc95745
--- /dev/null
+++ b/src/corelib/kernel/qmetaobjectbuilder_p.h
@@ -0,0 +1,269 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMETAOBJECTBUILDER_H
+#define QMETAOBJECTBUILDER_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmap.h>
+
+class QMetaObjectBuilderPrivate;
+class QMetaMethodBuilder;
+class QMetaMethodBuilderPrivate;
+class QMetaPropertyBuilder;
+class QMetaPropertyBuilderPrivate;
+class QMetaEnumBuilder;
+class QMetaEnumBuilderPrivate;
+
+class Q_CORE_EXPORT QMetaObjectBuilder
+{
+public:
+ enum AddMember
+ {
+ ClassName = 0x00000001,
+ SuperClass = 0x00000002,
+ Methods = 0x00000004,
+ Signals = 0x00000008,
+ Slots = 0x00000010,
+ Constructors = 0x00000020,
+ Properties = 0x00000040,
+ Enumerators = 0x00000080,
+ ClassInfos = 0x00000100,
+ RelatedMetaObjects = 0x00000200,
+ StaticMetacall = 0x00000400,
+ PublicMethods = 0x00000800,
+ ProtectedMethods = 0x00001000,
+ PrivateMethods = 0x00002000,
+ AllMembers = 0x7FFFFFFF,
+ AllPrimaryMembers = 0x7FFFFBFC
+ };
+ Q_DECLARE_FLAGS(AddMembers, AddMember)
+
+ enum MetaObjectFlag {
+ DynamicMetaObject = 0x01
+ };
+ Q_DECLARE_FLAGS(MetaObjectFlags, MetaObjectFlag)
+
+ QMetaObjectBuilder();
+ explicit QMetaObjectBuilder(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
+ virtual ~QMetaObjectBuilder();
+
+ QByteArray className() const;
+ void setClassName(const QByteArray& name);
+
+ const QMetaObject *superClass() const;
+ void setSuperClass(const QMetaObject *meta);
+
+ MetaObjectFlags flags() const;
+ void setFlags(MetaObjectFlags);
+
+ int methodCount() const;
+ int constructorCount() const;
+ int propertyCount() const;
+ int enumeratorCount() const;
+ int classInfoCount() const;
+ int relatedMetaObjectCount() const;
+
+ QMetaMethodBuilder addMethod(const QByteArray& signature);
+ QMetaMethodBuilder addMethod(const QByteArray& signature, const QByteArray& returnType);
+ QMetaMethodBuilder addMethod(const QMetaMethod& prototype);
+
+ QMetaMethodBuilder addSlot(const QByteArray& signature);
+ QMetaMethodBuilder addSignal(const QByteArray& signature);
+
+ QMetaMethodBuilder addConstructor(const QByteArray& signature);
+ QMetaMethodBuilder addConstructor(const QMetaMethod& prototype);
+
+ QMetaPropertyBuilder addProperty(const QByteArray& name, const QByteArray& type, int notifierId=-1);
+ QMetaPropertyBuilder addProperty(const QMetaProperty& prototype);
+
+ QMetaEnumBuilder addEnumerator(const QByteArray& name);
+ QMetaEnumBuilder addEnumerator(const QMetaEnum& prototype);
+
+ int addClassInfo(const QByteArray& name, const QByteArray& value);
+
+ int addRelatedMetaObject(const QMetaObject *meta);
+
+ void addMetaObject(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
+
+ QMetaMethodBuilder method(int index) const;
+ QMetaMethodBuilder constructor(int index) const;
+ QMetaPropertyBuilder property(int index) const;
+ QMetaEnumBuilder enumerator(int index) const;
+ const QMetaObject *relatedMetaObject(int index) const;
+
+ QByteArray classInfoName(int index) const;
+ QByteArray classInfoValue(int index) const;
+
+ void removeMethod(int index);
+ void removeConstructor(int index);
+ void removeProperty(int index);
+ void removeEnumerator(int index);
+ void removeClassInfo(int index);
+ void removeRelatedMetaObject(int index);
+
+ int indexOfMethod(const QByteArray& signature);
+ int indexOfSignal(const QByteArray& signature);
+ int indexOfSlot(const QByteArray& signature);
+ int indexOfConstructor(const QByteArray& signature);
+ int indexOfProperty(const QByteArray& name);
+ int indexOfEnumerator(const QByteArray& name);
+ int indexOfClassInfo(const QByteArray& name);
+
+ typedef int (*StaticMetacallFunction)(QMetaObject::Call, int, void **);
+
+ QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction() const;
+ void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value);
+
+ QMetaObject *toMetaObject() const;
+
+#ifndef QT_NO_DATASTREAM
+ void serialize(QDataStream& stream) const;
+ void deserialize
+ (QDataStream& stream,
+ const QMap<QByteArray, const QMetaObject *>& references);
+#endif
+
+private:
+ Q_DISABLE_COPY(QMetaObjectBuilder);
+
+ QMetaObjectBuilderPrivate *d;
+
+ friend class QMetaMethodBuilder;
+ friend class QMetaPropertyBuilder;
+ friend class QMetaEnumBuilder;
+};
+
+class Q_CORE_EXPORT QMetaMethodBuilder
+{
+public:
+ QMetaMethodBuilder() : _mobj(0), _index(0) {}
+
+ int index() const;
+
+ QMetaMethod::MethodType methodType() const;
+ QByteArray signature() const;
+
+ QByteArray returnType() const;
+ void setReturnType(const QByteArray& value);
+
+ QList<QByteArray> parameterNames() const;
+ void setParameterNames(const QList<QByteArray>& value);
+
+ QByteArray tag() const;
+ void setTag(const QByteArray& value);
+
+ QMetaMethod::Access access() const;
+ void setAccess(QMetaMethod::Access value);
+
+ int attributes() const;
+ void setAttributes(int value);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+ friend class QMetaPropertyBuilder;
+
+ QMetaMethodBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaMethodBuilderPrivate *d_func() const;
+};
+
+class Q_CORE_EXPORT QMetaPropertyBuilder
+{
+public:
+ QMetaPropertyBuilder() : _mobj(0), _index(0) {}
+
+ int index() const { return _index; }
+
+ QByteArray name() const;
+ QByteArray type() const;
+
+ bool hasNotifySignal() const;
+ QMetaMethodBuilder notifySignal() const;
+ void setNotifySignal(const QMetaMethodBuilder& value);
+ void removeNotifySignal();
+
+ bool isReadable() const;
+ bool isWritable() const;
+ bool isResettable() const;
+ bool isDesignable() const;
+ bool isScriptable() const;
+ bool isStored() const;
+ bool isEditable() const;
+ bool isUser() const;
+ bool hasStdCppSet() const;
+ bool isEnumOrFlag() const;
+ bool isDynamic() const;
+
+ void setReadable(bool value);
+ void setWritable(bool value);
+ void setResettable(bool value);
+ void setDesignable(bool value);
+ void setScriptable(bool value);
+ void setStored(bool value);
+ void setEditable(bool value);
+ void setUser(bool value);
+ void setStdCppSet(bool value);
+ void setEnumOrFlag(bool value);
+ void setDynamic(bool value);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+
+ QMetaPropertyBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaPropertyBuilderPrivate *d_func() const;
+};
+
+class Q_CORE_EXPORT QMetaEnumBuilder
+{
+public:
+ QMetaEnumBuilder() : _mobj(0), _index(0) {}
+
+ int index() const { return _index; }
+
+ QByteArray name() const;
+
+ bool isFlag() const;
+ void setIsFlag(bool value);
+
+ int keyCount() const;
+ QByteArray key(int index) const;
+ int value(int index) const;
+
+ int addKey(const QByteArray& name, int value);
+ void removeKey(int index);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+
+ QMetaEnumBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaEnumBuilderPrivate *d_func() const;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::AddMembers)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::MetaObjectFlags)
+
+#endif
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 287ac30..e6aeeef 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -120,10 +120,12 @@ QObjectPrivate::QObjectPrivate(int version)
inEventHandler = false;
inThreadChangeEvent = false;
deleteWatch = 0;
+ metaObject = 0;
}
QObjectPrivate::~QObjectPrivate()
{
+ delete static_cast<QAbstractDynamicMetaObject*>(metaObject);
if (deleteWatch)
*deleteWatch = 1;
#ifndef QT_NO_USERDATA
@@ -429,7 +431,7 @@ QMetaCallEvent::~QMetaCallEvent()
*/
int QMetaCallEvent::placeMetaCall(QObject *object)
{
- return object->qt_metacall(QMetaObject::InvokeMetaMethod, id_, args_);
+ return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, id_, args_);
}
/*!
@@ -786,6 +788,14 @@ QObject::~QObject()
d->eventFilters.clear();
+ // As declarativeData is in a union with currentChildBeingDeleted, this must
+ // be done (and declarativeData set back to 0) before deleting children.
+ if(d->declarativeData) {
+ QDeclarativeData *dd = d->declarativeData;
+ d->declarativeData = 0;
+ dd->destroyed(this);
+ }
+
if (!d->children.isEmpty())
d->deleteChildren();
@@ -3045,10 +3055,10 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
}
#if defined(QT_NO_EXCEPTIONS)
- receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+ metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
#else
try {
- receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+ metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
} catch (...) {
locker.relock();
@@ -3752,6 +3762,7 @@ void qDeleteInEventHandler(QObject *o)
delete o;
}
+
QT_END_NAMESPACE
#include "moc_qobject.cpp"
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index dbec0a6..b6bdfb3 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -108,6 +108,7 @@ public:
uint inThreadChangeEvent : 1;
uint unused : 23;
int postedEvents;
+ QMetaObject *metaObject; // assert dynamic
};
@@ -378,6 +379,9 @@ inline QList<T> qFindChildren(const QObject *o, const QRegExp &re)
#endif // Q_MOC_RUN
+template <class T> inline const char * qobject_interface_iid()
+{ return 0; }
+
template <class T> inline T qobject_cast_helper(QObject *object, T)
{ return static_cast<T>(((T)0)->staticMetaObject.cast(object)); }
@@ -394,6 +398,8 @@ inline T qobject_cast(const QObject *object)
#ifndef Q_MOC_RUN
# define Q_DECLARE_INTERFACE(IFace, IId) \
+ template <> inline const char *qobject_interface_iid<IFace *>() \
+ { return IId; } \
template <> inline IFace *qobject_cast_helper<IFace *>(QObject *object, IFace *) \
{ return (IFace *)(object ? object->qt_metacast(IId) : 0); } \
template <> inline IFace *qobject_cast_helper<IFace *>(const QObject *object, IFace *) \
@@ -457,8 +463,13 @@ inline T qobject_cast(const QObject *object)
}
+template <class T> inline const char * qobject_interface_iid()
+{ return 0; }
+
#ifndef Q_MOC_RUN
# define Q_DECLARE_INTERFACE(IFace, IId) \
+ template <> inline const char *qobject_interface_iid<IFace *>() \
+ { return IId; } \
template <> inline IFace *qobject_cast<IFace *>(QObject *object) \
{ return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : 0)); } \
template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 96d79af..bc7995c 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -85,6 +85,13 @@ inline QObjectData::~QObjectData() {}
enum { QObjectPrivateVersion = QT_VERSION };
+class Q_CORE_EXPORT QDeclarativeData
+{
+public:
+ virtual ~QDeclarativeData() {}
+ virtual void destroyed(QObject *) {}
+};
+
class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{
Q_DECLARE_PUBLIC(QObject)
@@ -117,7 +124,10 @@ public:
// object currently activating the object
Sender *currentSender;
- QObject *currentChildBeingDeleted;
+ union {
+ QObject *currentChildBeingDeleted;
+ QDeclarativeData *declarativeData;
+ };
bool isSender(const QObject *receiver, const char *signal) const;
QObjectList receiverList(const char *signal) const;
@@ -217,6 +227,14 @@ private:
void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o);
+
+struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QMetaObject
+{
+ virtual ~QAbstractDynamicMetaObject() {}
+ virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; }
+ virtual int createProperty(const char *, const char *) { return -1; }
+};
+
QT_END_NAMESPACE
#endif // QOBJECT_P_H
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 3a22323..98cc108 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -77,6 +77,7 @@ class QString;
#endif
#define Q_CLASSINFO(name, value)
#define Q_INTERFACES(x)
+#define Q_CAST_INTERFACES(x)
#define Q_PROPERTY(text)
#define Q_OVERRIDE(text)
#define Q_ENUMS(x)
@@ -169,6 +170,7 @@ private:
#define Q_SIGNALS Q_SIGNALS
#define Q_CLASSINFO(name, value) Q_CLASSINFO(name, value)
#define Q_INTERFACES(x) Q_INTERFACES(x)
+#define Q_CAST_INTERFACES(x) Q_CAST_INTERFACES(x)
#define Q_PROPERTY(text) Q_PROPERTY(text)
#define Q_OVERRIDE(text) Q_OVERRIDE(text)
#define Q_ENUMS(x) Q_ENUMS(x)
@@ -428,6 +430,7 @@ struct Q_CORE_EXPORT QMetaObject
};
int static_metacall(Call, int, void **) const;
+ static int metacall(QObject *, Call, int, void **);
#ifdef QT3_SUPPORT
QT3_SUPPORT const char *superClassName() const;
@@ -439,6 +442,7 @@ struct Q_CORE_EXPORT QMetaObject
const uint *data;
const void *extradata;
} d;
+
};
struct QMetaObjectExtraData
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index 033b760..074575b 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -134,7 +134,7 @@ inline void v_construct(QVariant::Private *x, const void *copy, T * = 0)
template <class T>
inline void v_clear(QVariant::Private *d, T* = 0)
{
-
+
if (sizeof(T) > sizeof(QVariant::Private::Data)) {
//now we need to cast
//because QVariant::PrivateShared doesn't have a virtual destructor
diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp
new file mode 100644
index 0000000..3f84314
--- /dev/null
+++ b/src/corelib/statemachine/qabstractstate.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractstate.h"
+#include "qabstractstate_p.h"
+#include "qstate.h"
+#include "qstate_p.h"
+#include "qstatemachine.h"
+#include "qstatemachine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractState
+
+ \brief The QAbstractState class is the base class of states of a QStateMachine.
+
+ \since 4.6
+ \ingroup statemachine
+
+ The QAbstractState class is the abstract base class of states that are part
+ of a QStateMachine. It defines the interface that all state objects have in
+ common. QAbstractState is part of \l{The State Machine Framework}.
+
+ The entered() signal is emitted when the state has been entered. The
+ exited() signal is emitted when the state has been exited.
+
+ The parentState() function returns the state's parent state. The machine()
+ function returns the state machine that the state is part of.
+
+ \section1 Subclassing
+
+ The onEntry() function is called when the state is entered; reimplement this
+ function to perform custom processing when the state is entered.
+
+ The onExit() function is called when the state is exited; reimplement this
+ function to perform custom processing when the state is exited.
+*/
+
+QAbstractStatePrivate::QAbstractStatePrivate()
+{
+}
+
+QAbstractStatePrivate *QAbstractStatePrivate::get(QAbstractState *q)
+{
+ return q->d_func();
+}
+
+const QAbstractStatePrivate *QAbstractStatePrivate::get(const QAbstractState *q)
+{
+ return q->d_func();
+}
+
+QStateMachine *QAbstractStatePrivate::machine() const
+{
+ Q_Q(const QAbstractState);
+ QObject *par = q->parent();
+ while (par != 0) {
+ if (QStateMachine *mach = qobject_cast<QStateMachine*>(par))
+ return mach;
+ par = par->parent();
+ }
+ return 0;
+}
+
+void QAbstractStatePrivate::callOnEntry(QEvent *e)
+{
+ Q_Q(QAbstractState);
+ q->onEntry(e);
+}
+
+void QAbstractStatePrivate::callOnExit(QEvent *e)
+{
+ Q_Q(QAbstractState);
+ q->onExit(e);
+}
+
+void QAbstractStatePrivate::emitEntered()
+{
+ Q_Q(QAbstractState);
+ emit q->entered();
+}
+
+void QAbstractStatePrivate::emitExited()
+{
+ Q_Q(QAbstractState);
+ emit q->exited();
+}
+
+/*!
+ Constructs a new state with the given \a parent state.
+*/
+QAbstractState::QAbstractState(QState *parent)
+ : QObject(
+#ifndef QT_STATEMACHINE_SOLUTION
+ *new QAbstractStatePrivate,
+#endif
+ parent)
+#ifdef QT_STATEMACHINE_SOLUTION
+ , d_ptr(new QAbstractStatePrivate)
+#endif
+{
+#ifdef QT_STATEMACHINE_SOLUTION
+ d_ptr->q_ptr = this;
+#endif
+}
+
+/*!
+ \internal
+*/
+QAbstractState::QAbstractState(QAbstractStatePrivate &dd, QState *parent)
+ : QObject(
+#ifndef QT_STATEMACHINE_SOLUTION
+ dd,
+#endif
+ parent)
+#ifdef QT_STATEMACHINE_SOLUTION
+ , d_ptr(&dd)
+#endif
+{
+#ifdef QT_STATEMACHINE_SOLUTION
+ d_ptr->q_ptr = this;
+#endif
+}
+
+/*!
+ Destroys this state.
+*/
+QAbstractState::~QAbstractState()
+{
+#ifdef QT_STATEMACHINE_SOLUTION
+ delete d_ptr;
+#endif
+}
+
+/*!
+ Returns this state's parent state, or 0 if the state has no parent state.
+*/
+QState *QAbstractState::parentState() const
+{
+ return qobject_cast<QState*>(parent());
+}
+
+/*!
+ Returns the state machine that this state is part of, or 0 if the state is
+ not part of a state machine.
+*/
+QStateMachine *QAbstractState::machine() const
+{
+ Q_D(const QAbstractState);
+ return d->machine();
+}
+
+/*!
+ \fn QAbstractState::onExit(QEvent *event)
+
+ This function is called when the state is exited. The given \a event is what
+ caused the state to be exited. Reimplement this function to perform custom
+ processing when the state is exited.
+*/
+
+/*!
+ \fn QAbstractState::onEntry(QEvent *event)
+
+ This function is called when the state is entered. The given \a event is
+ what caused the state to be entered. Reimplement this function to perform
+ custom processing when the state is entered.
+*/
+
+/*!
+ \fn QAbstractState::entered()
+
+ This signal is emitted when the state has been entered (after onEntry() has
+ been called).
+*/
+
+/*!
+ \fn QAbstractState::exited()
+
+ This signal is emitted when the state has been exited (after onExit() has
+ been called).
+*/
+
+/*!
+ \reimp
+*/
+bool QAbstractState::event(QEvent *e)
+{
+ return QObject::event(e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h
new file mode 100644
index 0000000..f6b4b21
--- /dev/null
+++ b/src/corelib/statemachine/qabstractstate.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTSTATE_H
+#define QABSTRACTSTATE_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QState;
+class QStateMachine;
+
+class QAbstractStatePrivate;
+class Q_CORE_EXPORT QAbstractState : public QObject
+{
+ Q_OBJECT
+public:
+ ~QAbstractState();
+
+ QState *parentState() const;
+ QStateMachine *machine() const;
+
+Q_SIGNALS:
+ void entered();
+ void exited();
+
+protected:
+ QAbstractState(QState *parent = 0);
+
+ virtual void onEntry(QEvent *event) = 0;
+ virtual void onExit(QEvent *event) = 0;
+
+ bool event(QEvent *e);
+
+protected:
+#ifdef QT_STATEMACHINE_SOLUTION
+ QAbstractStatePrivate *d_ptr;
+#endif
+ QAbstractState(QAbstractStatePrivate &dd, QState *parent);
+
+private:
+ Q_DISABLE_COPY(QAbstractState)
+ Q_DECLARE_PRIVATE(QAbstractState)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h
new file mode 100644
index 0000000..6c09696
--- /dev/null
+++ b/src/corelib/statemachine/qabstractstate_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTSTATE_P_H
+#define QABSTRACTSTATE_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.
+//
+
+#ifndef QT_STATEMACHINE_SOLUTION
+#include <private/qobject_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QStateMachine;
+
+class QAbstractState;
+class Q_CORE_EXPORT QAbstractStatePrivate
+#ifndef QT_STATEMACHINE_SOLUTION
+ : public QObjectPrivate
+#endif
+{
+ Q_DECLARE_PUBLIC(QAbstractState)
+
+public:
+ QAbstractStatePrivate();
+
+ static QAbstractStatePrivate *get(QAbstractState *q);
+ static const QAbstractStatePrivate *get(const QAbstractState *q);
+
+ QStateMachine *machine() const;
+
+ void callOnEntry(QEvent *e);
+ void callOnExit(QEvent *e);
+
+ void emitEntered();
+ void emitExited();
+
+#ifdef QT_STATEMACHINE_SOLUTION
+ QAbstractState *q_ptr;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp
new file mode 100644
index 0000000..1897aa6
--- /dev/null
+++ b/src/corelib/statemachine/qabstracttransition.cpp
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstracttransition.h"
+#include "qabstracttransition_p.h"
+#include "qabstractstate.h"
+#include "qstate.h"
+#include "qstatemachine.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractTransition
+
+ \brief The QAbstractTransition class is the base class of transitions between QAbstractState objects.
+
+ \since 4.6
+ \ingroup statemachine
+
+ The QAbstractTransition class is the abstract base class of transitions
+ between states (QAbstractState objects) of a
+ QStateMachine. QAbstractTransition is part of \l{The State Machine
+ Framework}.
+
+ The sourceState() function returns the source of the transition. The
+ targetStates() function returns the targets of the transition. The machine()
+ function returns the state machine that the transition is part of.
+
+ Transitions can cause animations to be played. Use the addAnimation()
+ function to add an animation to the transition.
+
+ \section1 Subclassing
+
+ The eventTest() function is called by the state machine to determine whether
+ an event should trigger the transition. In your reimplementation you
+ typically check the event type and cast the event object to the proper type,
+ and check that one or more properties of the event meet your criteria.
+
+ The onTransition() function is called when the transition is triggered;
+ reimplement this function to perform custom processing for the transition.
+*/
+
+/*!
+ \property QAbstractTransition::sourceState
+
+ \brief the source state (parent) of this transition
+*/
+
+/*!
+ \property QAbstractTransition::targetState
+
+ \brief the target state of this transition
+*/
+
+/*!
+ \property QAbstractTransition::targetStates
+
+ \brief the target states of this transition
+
+ If multiple states are specified, all must be descendants of the same
+ parallel group state.
+*/
+
+QAbstractTransitionPrivate::QAbstractTransitionPrivate()
+{
+}
+
+QAbstractTransitionPrivate *QAbstractTransitionPrivate::get(QAbstractTransition *q)
+{
+ return q->d_func();
+}
+
+const QAbstractTransitionPrivate *QAbstractTransitionPrivate::get(const QAbstractTransition *q)
+{
+ return q->d_func();
+}
+
+QStateMachine *QAbstractTransitionPrivate::machine() const
+{
+ Q_Q(const QAbstractTransition);
+ QObject *par = q->parent();
+ while (par != 0) {
+ if (QStateMachine *mach = qobject_cast<QStateMachine*>(par))
+ return mach;
+ par = par->parent();
+ }
+ return 0;
+}
+
+bool QAbstractTransitionPrivate::callEventTest(QEvent *e) const
+{
+ Q_Q(const QAbstractTransition);
+ return q->eventTest(e);
+}
+
+void QAbstractTransitionPrivate::callOnTransition(QEvent *e)
+{
+ Q_Q(QAbstractTransition);
+ q->onTransition(e);
+}
+
+QState *QAbstractTransitionPrivate::sourceState() const
+{
+ Q_Q(const QAbstractTransition);
+ return qobject_cast<QState*>(q->parent());
+}
+
+/*!
+ Constructs a new QAbstractTransition object with the given \a sourceState.
+*/
+QAbstractTransition::QAbstractTransition(QState *sourceState)
+ : QObject(
+#ifndef QT_STATEMACHINE_SOLUTION
+ *new QAbstractTransitionPrivate,
+#endif
+ sourceState)
+#ifdef QT_STATEMACHINE_SOLUTION
+ , d_ptr(new QAbstractTransitionPrivate)
+#endif
+{
+#ifdef QT_STATEMACHINE_SOLUTION
+ d_ptr->q_ptr = this;
+#endif
+}
+
+/*!
+ Constructs a new QAbstractTransition object with the given \a targets and \a
+ sourceState.
+*/
+QAbstractTransition::QAbstractTransition(const QList<QAbstractState*> &targets,
+ QState *sourceState)
+ : QObject(
+#ifndef QT_STATEMACHINE_SOLUTION
+ *new QAbstractTransitionPrivate,
+#endif
+ sourceState)
+#ifdef QT_STATEMACHINE_SOLUTION
+ , d_ptr(new QAbstractTransitionPrivate)
+#endif
+{
+#ifdef QT_STATEMACHINE_SOLUTION
+ d_ptr->q_ptr = this;
+#endif
+ Q_D(QAbstractTransition);
+ d->targetStates = targets;
+}
+
+/*!
+ \internal
+*/
+QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd,
+ QState *parent)
+ : QObject(
+#ifndef QT_STATEMACHINE_SOLUTION
+ dd,
+#endif
+ parent)
+#ifdef QT_STATEMACHINE_SOLUTION
+ , d_ptr(&dd)
+#endif
+{
+#ifdef QT_STATEMACHINE_SOLUTION
+ d_ptr->q_ptr = this;
+#endif
+}
+
+/*!
+ \internal
+*/
+QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd,
+ const QList<QAbstractState*> &targets,
+ QState *parent)
+ : QObject(
+#ifndef QT_STATEMACHINE_SOLUTION
+ dd,
+#endif
+ parent)
+#ifdef QT_STATEMACHINE_SOLUTION
+ , d_ptr(&dd)
+#endif
+{
+#ifdef QT_STATEMACHINE_SOLUTION
+ d_ptr->q_ptr = this;
+#endif
+ Q_D(QAbstractTransition);
+ d->targetStates = targets;
+}
+
+/*!
+ Destroys this transition.
+*/
+QAbstractTransition::~QAbstractTransition()
+{
+#ifdef QT_STATEMACHINE_SOLUTION
+ delete d_ptr;
+#endif
+}
+
+/*!
+ Returns the source state of this transition, or 0 if this transition has no
+ source state.
+*/
+QState *QAbstractTransition::sourceState() const
+{
+ Q_D(const QAbstractTransition);
+ return d->sourceState();
+}
+
+/*!
+ Returns the target state of this transition, or 0 if the transition has no
+ target.
+*/
+QAbstractState *QAbstractTransition::targetState() const
+{
+ Q_D(const QAbstractTransition);
+ if (d->targetStates.isEmpty())
+ return 0;
+ return d->targetStates.first();
+}
+
+/*!
+ Sets the \a target state of this transition.
+*/
+void QAbstractTransition::setTargetState(QAbstractState* target)
+{
+ Q_D(QAbstractTransition);
+ if (!target)
+ d->targetStates.clear();
+ else
+ d->targetStates = QList<QAbstractState*>() << target;
+}
+
+/*!
+ Returns the target states of this transition, or an empty list if this
+ transition has no target states.
+*/
+QList<QAbstractState*> QAbstractTransition::targetStates() const
+{
+ Q_D(const QAbstractTransition);
+ return d->targetStates;
+}
+
+/*!
+ Sets the target states of this transition to be the given \a targets.
+*/
+void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets)
+{
+ Q_D(QAbstractTransition);
+ d->targetStates = targets;
+}
+
+/*!
+ Returns the state machine that this transition is part of, or 0 if the
+ transition is not part of a state machine.
+*/
+QStateMachine *QAbstractTransition::machine() const
+{
+ Q_D(const QAbstractTransition);
+ return d->machine();
+}
+
+#ifndef QT_NO_ANIMATION
+
+/*!
+ Adds the given \a animation to this transition.
+ The transition does not take ownership of the animation.
+
+ \sa removeAnimation(), animations()
+*/
+void QAbstractTransition::addAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAbstractTransition);
+ if (!animation) {
+ qWarning("QAbstractTransition::addAnimation: cannot add null animation");
+ return;
+ }
+ d->animations.append(animation);
+}
+
+/*!
+ Removes the given \a animation from this transition.
+
+ \sa addAnimation()
+*/
+void QAbstractTransition::removeAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAbstractTransition);
+ if (!animation) {
+ qWarning("QAbstractTransition::removeAnimation: cannot remove null animation");
+ return;
+ }
+ d->animations.removeOne(animation);
+}
+
+/*!
+ Returns the list of animations associated with this transition, or an empty
+ list if it has no animations.
+
+ \sa addAnimation()
+*/
+QList<QAbstractAnimation*> QAbstractTransition::animations() const
+{
+ Q_D(const QAbstractTransition);
+ return d->animations;
+}
+
+#endif
+
+/*!
+ \fn QAbstractTransition::eventTest(QEvent *event) const
+
+ This function is called to determine whether the given \a event should cause
+ this transition to trigger. Reimplement this function and return true if the
+ event should trigger the transition, otherwise return false.
+*/
+
+/*!
+ \fn QAbstractTransition::onTransition(QEvent *event)
+
+ This function is called when the transition is triggered. The given \a event
+ is what caused the transition to trigger. Reimplement this function to
+ perform custom processing when the transition is triggered.
+*/
+
+/*!
+ \reimp
+*/
+bool QAbstractTransition::event(QEvent *e)
+{
+ return QObject::event(e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h
new file mode 100644
index 0000000..e207944
--- /dev/null
+++ b/src/corelib/statemachine/qabstracttransition.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTTRANSITION_H
+#define QABSTRACTTRANSITION_H
+
+#include <QtCore/qobject.h>
+
+#include <QtCore/qlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEvent;
+class QAbstractState;
+class QState;
+class QStateMachine;
+
+#ifndef QT_NO_ANIMATION
+class QAbstractAnimation;
+#endif
+
+class QAbstractTransitionPrivate;
+class Q_CORE_EXPORT QAbstractTransition : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QState* sourceState READ sourceState)
+ Q_PROPERTY(QAbstractState* targetState READ targetState WRITE setTargetState)
+ Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates)
+public:
+ QAbstractTransition(QState *sourceState = 0);
+ QAbstractTransition(const QList<QAbstractState*> &targets, QState *sourceState = 0);
+ virtual ~QAbstractTransition();
+
+ QState *sourceState() const;
+ QAbstractState *targetState() const;
+ void setTargetState(QAbstractState* target);
+ QList<QAbstractState*> targetStates() const;
+ void setTargetStates(const QList<QAbstractState*> &targets);
+
+ QStateMachine *machine() const;
+
+#ifndef QT_NO_ANIMATION
+ void addAnimation(QAbstractAnimation *animation);
+ void removeAnimation(QAbstractAnimation *animation);
+ QList<QAbstractAnimation*> animations() const;
+#endif
+
+protected:
+ virtual bool eventTest(QEvent *event) const = 0;
+
+ virtual void onTransition(QEvent *event) = 0;
+
+ bool event(QEvent *e);
+
+protected:
+#ifdef QT_STATEMACHINE_SOLUTION
+ QAbstractTransitionPrivate *d_ptr;
+#endif
+ QAbstractTransition(QAbstractTransitionPrivate &dd, QState *parent);
+ QAbstractTransition(QAbstractTransitionPrivate &dd,
+ const QList<QAbstractState*> &targets, QState *parent);
+
+private:
+ Q_DISABLE_COPY(QAbstractTransition)
+ Q_DECLARE_PRIVATE(QAbstractTransition)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h
new file mode 100644
index 0000000..b4e1c88
--- /dev/null
+++ b/src/corelib/statemachine/qabstracttransition_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTTRANSITION_P_H
+#define QABSTRACTTRANSITION_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.
+//
+
+#ifndef QT_STATEMACHINE_SOLUTION
+#include <private/qobject_p.h>
+#endif
+
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractState;
+class QState;
+class QStateMachine;
+
+class QAbstractTransition;
+class Q_CORE_EXPORT QAbstractTransitionPrivate
+#ifndef QT_STATEMACHINE_SOLUTION
+ : public QObjectPrivate
+#endif
+{
+ Q_DECLARE_PUBLIC(QAbstractTransition)
+public:
+ QAbstractTransitionPrivate();
+
+ static QAbstractTransitionPrivate *get(QAbstractTransition *q);
+ static const QAbstractTransitionPrivate *get(const QAbstractTransition *q);
+
+ bool callEventTest(QEvent *e) const;
+ void callOnTransition(QEvent *e);
+ QState *sourceState() const;
+ QStateMachine *machine() const;
+
+ QList<QAbstractState*> targetStates;
+
+#ifndef QT_NO_ANIMATION
+ QList<QAbstractAnimation*> animations;
+#endif
+
+#ifdef QT_STATEMACHINE_SOLUTION
+ QAbstractTransition *q_ptr;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp
new file mode 100644
index 0000000..86259e4
--- /dev/null
+++ b/src/corelib/statemachine/qeventtransition.cpp
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventtransition.h"
+#include "qeventtransition_p.h"
+#include "qwrappedevent.h"
+#include "qstate.h"
+#include "qstate_p.h"
+#include "qstatemachine.h"
+#include "qstatemachine_p.h"
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QEventTransition
+
+ \brief The QEventTransition class provides a QObject-specific transition for Qt events.
+
+ \since 4.6
+ \ingroup statemachine
+
+ A QEventTransition object binds an event to a particular QObject.
+ QEventTransition is part of \l{The State Machine Framework}.
+
+ Example:
+
+ \code
+ QPushButton *button = ...;
+ QState *s1 = ...;
+ QState *s2 = ...;
+ // If in s1 and the button receives an Enter event, transition to s2
+ QEventTransition *enterTransition = new QEventTransition(button, QEvent::Enter);
+ enterTransition->setTargetState(s2);
+ s1->addTransition(enterTransition);
+ // If in s2 and the button receives an Exit event, transition back to s1
+ QEventTransition *leaveTransition = new QEventTransition(button, QEvent::Leave);
+ leaveTransition->setTargetState(s1);
+ s2->addTransition(leaveTransition);
+ \endcode
+
+ \section1 Subclassing
+
+ When reimplementing the eventTest() function, you should first call the base
+ implementation to verify that the event is a QWrappedEvent for the proper
+ object and event type. You may then cast the event to a QWrappedEvent and
+ get the original event by calling QWrappedEvent::event(), and perform
+ additional checks on that object.
+
+ \sa QState::addTransition()
+*/
+
+/*!
+ \property QEventTransition::eventObject
+
+ \brief the event source that this event transition is associated with
+*/
+
+/*!
+ \property QEventTransition::eventType
+
+ \brief the type of event that this event transition is associated with
+*/
+QEventTransitionPrivate::QEventTransitionPrivate()
+{
+ object = 0;
+ eventType = QEvent::None;
+ registered = false;
+}
+
+QEventTransitionPrivate *QEventTransitionPrivate::get(QEventTransition *q)
+{
+ return q->d_func();
+}
+
+void QEventTransitionPrivate::invalidate()
+{
+ Q_Q(QEventTransition);
+ if (registered) {
+ QState *source = sourceState();
+ QStatePrivate *source_d = QStatePrivate::get(source);
+ QStateMachinePrivate *mach = QStateMachinePrivate::get(source_d->machine());
+ if (mach) {
+ mach->unregisterEventTransition(q);
+ if (mach->configuration.contains(source))
+ mach->registerEventTransition(q);
+ }
+ }
+}
+
+/*!
+ Constructs a new QEventTransition object with the given \a sourceState.
+*/
+QEventTransition::QEventTransition(QState *sourceState)
+ : QAbstractTransition(*new QEventTransitionPrivate, sourceState)
+{
+}
+
+/*!
+ Constructs a new QEventTransition object associated with events of the given
+ \a type for the given \a object, and with the given \a sourceState.
+*/
+QEventTransition::QEventTransition(QObject *object, QEvent::Type type,
+ QState *sourceState)
+ : QAbstractTransition(*new QEventTransitionPrivate, sourceState)
+{
+ Q_D(QEventTransition);
+ d->registered = false;
+ d->object = object;
+ d->eventType = type;
+}
+
+/*!
+ Constructs a new QEventTransition object associated with events of the given
+ \a type for the given \a object. The transition has the given \a targets and
+ \a sourceState.
+*/
+QEventTransition::QEventTransition(QObject *object, QEvent::Type type,
+ const QList<QAbstractState*> &targets,
+ QState *sourceState)
+ : QAbstractTransition(*new QEventTransitionPrivate, targets, sourceState)
+{
+ Q_D(QEventTransition);
+ d->registered = false;
+ d->object = object;
+ d->eventType = type;
+}
+
+/*!
+ \internal
+*/
+QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent)
+ : QAbstractTransition(dd, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object,
+ QEvent::Type type, QState *parent)
+ : QAbstractTransition(dd, parent)
+{
+ Q_D(QEventTransition);
+ d->registered = false;
+ d->object = object;
+ d->eventType = type;
+}
+
+/*!
+ \internal
+*/
+QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object,
+ QEvent::Type type, const QList<QAbstractState*> &targets,
+ QState *parent)
+ : QAbstractTransition(dd, targets, parent)
+{
+ Q_D(QEventTransition);
+ d->registered = false;
+ d->object = object;
+ d->eventType = type;
+}
+
+/*!
+ Destroys this QObject event transition.
+*/
+QEventTransition::~QEventTransition()
+{
+}
+
+/*!
+ Returns the event type that this event transition is associated with.
+*/
+QEvent::Type QEventTransition::eventType() const
+{
+ Q_D(const QEventTransition);
+ return d->eventType;
+}
+
+/*!
+ Sets the event \a type that this event transition is associated with.
+*/
+void QEventTransition::setEventType(QEvent::Type type)
+{
+ Q_D(QEventTransition);
+ if (d->eventType == type)
+ return;
+ d->eventType = type;
+ d->invalidate();
+}
+
+/*!
+ Returns the event source associated with this event transition.
+*/
+QObject *QEventTransition::eventObject() const
+{
+ Q_D(const QEventTransition);
+ return d->object;
+}
+
+/*!
+ Sets the event source associated with this event transition to be the given
+ \a object.
+*/
+void QEventTransition::setEventObject(QObject *object)
+{
+ Q_D(QEventTransition);
+ if (d->object == object)
+ return;
+ d->object = object;
+ d->invalidate();
+}
+
+/*!
+ \reimp
+*/
+bool QEventTransition::eventTest(QEvent *event) const
+{
+ Q_D(const QEventTransition);
+#ifdef QT_STATEMACHINE_SOLUTION
+ if (event->type() == QEvent::Type(QEvent::User-3)) {
+#else
+ if (event->type() == QEvent::Wrapped) {
+#endif
+ QWrappedEvent *we = static_cast<QWrappedEvent*>(event);
+ return (we->object() == d->object)
+ && (we->event()->type() == d->eventType);
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QEventTransition::onTransition(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+bool QEventTransition::event(QEvent *e)
+{
+ return QAbstractTransition::event(e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h
new file mode 100644
index 0000000..a128cee
--- /dev/null
+++ b/src/corelib/statemachine/qeventtransition.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTTRANSITION_H
+#define QEVENTTRANSITION_H
+
+#ifndef QT_STATEMACHINE_SOLUTION
+#include <QtCore/qabstracttransition.h>
+#else
+#include "qabstracttransition.h"
+#endif
+#include <QtCore/qcoreevent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEventTransitionPrivate;
+class Q_CORE_EXPORT QEventTransition : public QAbstractTransition
+{
+ Q_OBJECT
+ Q_PROPERTY(QObject* eventObject READ eventObject WRITE setEventObject)
+#ifndef QT_STATEMACHINE_SOLUTION
+ Q_PROPERTY(QEvent::Type eventType READ eventType WRITE setEventType)
+#endif
+public:
+ QEventTransition(QState *sourceState = 0);
+ QEventTransition(QObject *object, QEvent::Type type, QState *sourceState = 0);
+ QEventTransition(QObject *object, QEvent::Type type,
+ const QList<QAbstractState*> &targets, QState *sourceState = 0);
+ ~QEventTransition();
+
+ QObject *eventObject() const;
+ void setEventObject(QObject *object);
+
+ QEvent::Type eventType() const;
+ void setEventType(QEvent::Type type);
+
+protected:
+ bool eventTest(QEvent *event) const;
+ void onTransition(QEvent *event);
+
+ bool event(QEvent *e);
+
+protected:
+ QEventTransition(QEventTransitionPrivate &dd, QState *parent);
+ QEventTransition(QEventTransitionPrivate &dd, QObject *object,
+ QEvent::Type type, QState *parent);
+ QEventTransition(QEventTransitionPrivate &dd, QObject *object,
+ QEvent::Type type, const QList<QAbstractState*> &targets,
+ QState *parent);
+
+private:
+ Q_DISABLE_COPY(QEventTransition)
+ Q_DECLARE_PRIVATE(QEventTransition)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qeventtransition_p.h b/src/corelib/statemachine/qeventtransition_p.h
new file mode 100644
index 0000000..fca8c0d
--- /dev/null
+++ b/src/corelib/statemachine/qeventtransition_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTTRANSITION_P_H
+#define QEVENTTRANSITION_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 "qabstracttransition_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEventTransition;
+class Q_CORE_EXPORT QEventTransitionPrivate : public QAbstractTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QEventTransition)
+public:
+ QEventTransitionPrivate();
+
+ static QEventTransitionPrivate *get(QEventTransition *q);
+
+ void invalidate();
+
+ bool registered;
+ QObject *object;
+ QEvent::Type eventType;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qfinalstate.cpp b/src/corelib/statemachine/qfinalstate.cpp
new file mode 100644
index 0000000..0980336
--- /dev/null
+++ b/src/corelib/statemachine/qfinalstate.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfinalstate.h"
+#include "qabstractstate_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QFinalState
+
+ \brief The QFinalState class provides a final state.
+
+ \since 4.6
+ \ingroup statemachine
+
+ A final state is used to communicate that (part of) a QStateMachine has
+ finished its work. When a final top-level state is entered, the state
+ machine's \l{QStateMachine::finished()}{finished}() signal is emitted. In
+ general, when a final substate (a child of a QState) is entered, the parent
+ state's \l{QState::finished()}{finished}() signal is emitted. QFinalState
+ is part of \l{The State Machine Framework}.
+
+ To use a final state, you create a QFinalState object and add a transition
+ to it from another state. Example:
+
+ \code
+ QPushButton button;
+
+ QStateMachine machine;
+ QState *s1 = new QState();
+ QFinalState *s2 = new QFinalState();
+ s1->addTransition(&button, SIGNAL(clicked()), s2);
+ machine.addState(s1);
+ machine.addState(s2);
+
+ QObject::connect(&machine, SIGNAL(finished()), QApplication::instance(), SLOT(quit()));
+ machine.setInitialState(s1);
+ machine.start();
+ \endcode
+
+ \sa QStateMachine::finished(), QState::finished()
+*/
+
+class QFinalStatePrivate : public QAbstractStatePrivate
+{
+ Q_DECLARE_PUBLIC(QFinalState)
+
+public:
+ QFinalStatePrivate();
+};
+
+QFinalStatePrivate::QFinalStatePrivate()
+{
+}
+
+/*!
+ Constructs a new QFinalState object with the given \a parent state.
+*/
+QFinalState::QFinalState(QState *parent)
+ : QAbstractState(*new QFinalStatePrivate, parent)
+{
+}
+
+/*!
+ Destroys this final state.
+*/
+QFinalState::~QFinalState()
+{
+}
+
+/*!
+ \reimp
+*/
+void QFinalState::onEntry(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+void QFinalState::onExit(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+bool QFinalState::event(QEvent *e)
+{
+ return QAbstractState::event(e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/statemachine/qfinalstate.h b/src/corelib/statemachine/qfinalstate.h
new file mode 100644
index 0000000..eb8aa0f
--- /dev/null
+++ b/src/corelib/statemachine/qfinalstate.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFINALSTATE_H
+#define QFINALSTATE_H
+
+#ifndef QT_STATEMACHINE_SOLUTION
+#include <QtCore/qabstractstate.h>
+#else
+#include "qabstractstate.h"
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QFinalStatePrivate;
+class Q_CORE_EXPORT QFinalState : public QAbstractState
+{
+ Q_OBJECT
+public:
+ QFinalState(QState *parent = 0);
+ ~QFinalState();
+
+protected:
+ void onEntry(QEvent *event);
+ void onExit(QEvent *event);
+
+ bool event(QEvent *e);
+
+private:
+ Q_DISABLE_COPY(QFinalState)
+ Q_DECLARE_PRIVATE(QFinalState)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp
new file mode 100644
index 0000000..d1b2391
--- /dev/null
+++ b/src/corelib/statemachine/qhistorystate.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhistorystate.h"
+#include "qhistorystate_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QHistoryState
+
+ \brief The QHistoryState class provides a means of returning to a previously active substate.
+
+ \since 4.6
+ \ingroup statemachine
+
+ A history state is a pseudo-state that represents the child state that the
+ parent state was in the last time the parent state was exited. A transition
+ with a history state as its target is in fact a transition to one of the
+ other child states of the parent state. QHistoryState is part of \l{The
+ State Machine Framework}.
+
+ Use the setDefaultState() function to set the state that should be entered
+ if the parent state has never been entered. Example:
+
+ \code
+ QStateMachine machine;
+
+ QState *s1 = new QState();
+ QState *s11 = new QState(s1);
+ QState *s12 = new QState(s1);
+
+ QHistoryState *s1h = new QHistoryState(s1);
+ s1h->setDefaultState(s11);
+
+ machine.addState(s1);
+
+ QState *s2 = new QState();
+ machine.addState(s2);
+
+ QPushButton *button = new QPushButton();
+ // Clicking the button will cause the state machine to enter the child state
+ // that s1 was in the last time s1 was exited, or the history state's default
+ // state if s1 has never been entered.
+ s1->addTransition(button, SIGNAL(clicked()), s1h);
+ \endcode
+
+ By default a history state is shallow, meaning that it won't remember nested
+ states. This can be configured through the historyType property.
+*/
+
+/*!
+ \property QHistoryState::defaultState
+
+ \brief the default state of this history state
+*/
+
+/*!
+ \property QHistoryState::historyType
+
+ \brief the type of history that this history state records
+
+ The default value of this property is QHistoryState::ShallowHistory.
+*/
+
+/*!
+ \enum QHistoryState::HistoryType
+
+ This enum specifies the type of history that a QHistoryState records.
+
+ \value ShallowHistory Only the immediate child states of the parent state
+ are recorded. In this case a transition with the history state as its
+ target will end up in the immediate child state that the parent was in the
+ last time it was exited. This is the default.
+
+ \value DeepHistory Nested states are recorded. In this case a transition
+ with the history state as its target will end up in the most deeply nested
+ descendant state the parent was in the last time it was exited.
+*/
+
+QHistoryStatePrivate::QHistoryStatePrivate()
+ : defaultState(0)
+{
+}
+
+QHistoryStatePrivate *QHistoryStatePrivate::get(QHistoryState *q)
+{
+ return q->d_func();
+}
+
+const QHistoryStatePrivate *QHistoryStatePrivate::get(const QHistoryState *q)
+{
+ return q->d_func();
+}
+
+/*!
+ Constructs a new shallow history state with the given \a parent state.
+*/
+QHistoryState::QHistoryState(QState *parent)
+ : QAbstractState(*new QHistoryStatePrivate, parent)
+{
+ Q_D(QHistoryState);
+ d->historyType = ShallowHistory;
+}
+/*!
+ Constructs a new history state of the given \a type, with the given \a
+ parent state.
+*/
+QHistoryState::QHistoryState(HistoryType type, QState *parent)
+ : QAbstractState(*new QHistoryStatePrivate, parent)
+{
+ Q_D(QHistoryState);
+ d->historyType = type;
+}
+
+/*!
+ Destroys this history state.
+*/
+QHistoryState::~QHistoryState()
+{
+}
+
+/*!
+ Returns this history state's default state. The default state indicates the
+ state to transition to if the parent state has never been entered before.
+*/
+QAbstractState *QHistoryState::defaultState() const
+{
+ Q_D(const QHistoryState);
+ return d->defaultState;
+}
+
+/*!
+ Sets this history state's default state to be the given \a state.
+ \a state must be a sibling of this history state.
+*/
+void QHistoryState::setDefaultState(QAbstractState *state)
+{
+ Q_D(QHistoryState);
+ if (state && state->parentState() != parentState()) {
+ qWarning("QHistoryState::setDefaultState: state %p does not belong "
+ "to this history state's group (%p)", state, parentState());
+ return;
+ }
+ d->defaultState = state;
+}
+
+/*!
+ Returns the type of history that this history state records.
+*/
+QHistoryState::HistoryType QHistoryState::historyType() const
+{
+ Q_D(const QHistoryState);
+ return d->historyType;
+}
+
+/*!
+ Sets the \a type of history that this history state records.
+*/
+void QHistoryState::setHistoryType(HistoryType type)
+{
+ Q_D(QHistoryState);
+ d->historyType = type;
+}
+
+/*!
+ \reimp
+*/
+void QHistoryState::onEntry(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+void QHistoryState::onExit(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+bool QHistoryState::event(QEvent *e)
+{
+ return QAbstractState::event(e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h
new file mode 100644
index 0000000..d0f75de
--- /dev/null
+++ b/src/corelib/statemachine/qhistorystate.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHISTORYSTATE_H
+#define QHISTORYSTATE_H
+
+#ifndef QT_STATEMACHINE_SOLUTION
+#include <QtCore/qabstractstate.h>
+#else
+#include "qabstractstate.h"
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QHistoryStatePrivate;
+class Q_CORE_EXPORT QHistoryState : public QAbstractState
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractState* defaultState READ defaultState WRITE setDefaultState)
+ Q_PROPERTY(HistoryType historyType READ historyType WRITE setHistoryType)
+ Q_ENUMS(HistoryType)
+public:
+ enum HistoryType {
+ ShallowHistory,
+ DeepHistory
+ };
+
+ QHistoryState(QState *parent = 0);
+ QHistoryState(HistoryType type, QState *parent = 0);
+ ~QHistoryState();
+
+ QAbstractState *defaultState() const;
+ void setDefaultState(QAbstractState *state);
+
+ HistoryType historyType() const;
+ void setHistoryType(HistoryType type);
+
+protected:
+ void onEntry(QEvent *event);
+ void onExit(QEvent *event);
+
+ bool event(QEvent *e);
+
+private:
+ Q_DISABLE_COPY(QHistoryState)
+ Q_DECLARE_PRIVATE(QHistoryState)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qhistorystate_p.h b/src/corelib/statemachine/qhistorystate_p.h
new file mode 100644
index 0000000..2f17496
--- /dev/null
+++ b/src/corelib/statemachine/qhistorystate_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHISTORYSTATE_P_H
+#define QHISTORYSTATE_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 "qabstractstate_p.h"
+
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QHistoryState;
+class QHistoryStatePrivate : public QAbstractStatePrivate
+{
+ Q_DECLARE_PUBLIC(QHistoryState)
+
+public:
+ QHistoryStatePrivate();
+
+ static QHistoryStatePrivate *get(QHistoryState *q);
+ static const QHistoryStatePrivate *get(const QHistoryState *q);
+
+ QAbstractState *defaultState;
+ QHistoryState::HistoryType historyType;
+ QList<QAbstractState*> configuration;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qsignalevent.h b/src/corelib/statemachine/qsignalevent.h
new file mode 100644
index 0000000..8221f68
--- /dev/null
+++ b/src/corelib/statemachine/qsignalevent.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIGNALEVENT_H
+#define QSIGNALEVENT_H
+
+#include <QtCore/qcoreevent.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QSignalEvent : public QEvent
+{
+public:
+ QSignalEvent(const QObject *sender, int signalIndex,
+ const QList<QVariant> &arguments);
+ ~QSignalEvent();
+
+ inline const QObject *sender() const { return m_sender; }
+ inline int signalIndex() const { return m_signalIndex; }
+ inline QList<QVariant> arguments() const { return m_arguments; }
+
+private:
+ const QObject *m_sender;
+ int m_signalIndex;
+ QList<QVariant> m_arguments;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qsignaleventgenerator_p.h b/src/corelib/statemachine/qsignaleventgenerator_p.h
new file mode 100644
index 0000000..d18def8
--- /dev/null
+++ b/src/corelib/statemachine/qsignaleventgenerator_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIGNALEVENTGENERATOR_P_H
+#define QSIGNALEVENTGENERATOR_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/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class QStateMachine;
+
+class QSignalEventGenerator : public QObject
+{
+public:
+ QSignalEventGenerator(
+#ifdef QT_STATEMACHINE_SOLUTION
+ int signalIndex,
+#endif
+ QStateMachine *parent);
+
+ static const QMetaObject staticMetaObject;
+ virtual const QMetaObject *metaObject() const;
+ virtual void *qt_metacast(const char *);
+ virtual int qt_metacall(QMetaObject::Call, int, void **argv);
+
+private:
+#ifdef QT_STATEMACHINE_SOLUTION
+ int signalIndex;
+#endif
+ Q_DISABLE_COPY(QSignalEventGenerator)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp
new file mode 100644
index 0000000..d5833bd
--- /dev/null
+++ b/src/corelib/statemachine/qsignaltransition.cpp
@@ -0,0 +1,261 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsignaltransition.h"
+#include "qsignaltransition_p.h"
+#include "qsignalevent.h"
+#include "qstate.h"
+#include "qstate_p.h"
+#include "qstatemachine.h"
+#include "qstatemachine_p.h"
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSignalTransition
+
+ \brief The QSignalTransition class provides a transition based on a Qt signal.
+
+ \since 4.6
+ \ingroup statemachine
+
+ Typically you would use the overload of QState::addTransition() that takes a
+ sender and signal as arguments, rather than creating QSignalTransition
+ objects directly. QSignalTransition is part of \l{The State Machine
+ Framework}.
+
+ You can subclass QSignalTransition and reimplement eventTest() to make a
+ signal transition conditional; the event object passed to eventTest() will
+ be a QSignalEvent object. Example:
+
+ \code
+ class CheckedTransition : public QSignalTransition
+ {
+ public:
+ CheckedTransition(QCheckBox *check)
+ : QSignalTransition(check, SIGNAL(stateChanged(int))) {}
+ protected:
+ bool eventTest(QEvent *e) const {
+ if (!QSignalTransition::eventTest(e))
+ return false;
+ QSignalEvent *se = static_cast<QSignalEvent*>(e);
+ return (se->arguments().at(0).toInt() == Qt::Checked);
+ }
+ };
+
+ ...
+
+ QCheckBox *check = new QCheckBox();
+ check->setTristate(true);
+
+ QState *s1 = new QState();
+ QState *s2 = new QState();
+ CheckedTransition *t1 = new CheckedTransition(check);
+ t1->setTargetState(s2);
+ s1->addTransition(t1);
+ \endcode
+*/
+
+/*!
+ \property QSignalTransition::senderObject
+
+ \brief the sender object that this signal transition is associated with
+*/
+
+/*!
+ \property QSignalTransition::signal
+
+ \brief the signal that this signal transition is associated with
+*/
+
+QSignalTransitionPrivate::QSignalTransitionPrivate()
+{
+ sender = 0;
+ signalIndex = -1;
+}
+
+QSignalTransitionPrivate *QSignalTransitionPrivate::get(QSignalTransition *q)
+{
+ return q->d_func();
+}
+
+void QSignalTransitionPrivate::invalidate()
+{
+ Q_Q(QSignalTransition);
+ if (signalIndex != -1) {
+ QState *source = sourceState();
+ QStatePrivate *source_d = QStatePrivate::get(source);
+ QStateMachinePrivate *mach = QStateMachinePrivate::get(source_d->machine());
+ if (mach) {
+ mach->unregisterSignalTransition(q);
+ if (mach->configuration.contains(source))
+ mach->registerSignalTransition(q);
+ }
+ }
+}
+
+/*!
+ Constructs a new signal transition with the given \a sourceState.
+*/
+QSignalTransition::QSignalTransition(QState *sourceState)
+ : QAbstractTransition(*new QSignalTransitionPrivate, sourceState)
+{
+}
+
+/*!
+ Constructs a new signal transition associated with the given \a signal of
+ the given \a sender, and with the given \a sourceState.
+*/
+QSignalTransition::QSignalTransition(QObject *sender, const char *signal,
+ QState *sourceState)
+ : QAbstractTransition(*new QSignalTransitionPrivate, sourceState)
+{
+ Q_D(QSignalTransition);
+ d->sender = sender;
+ d->signal = signal;
+}
+
+/*!
+ Constructs a new signal transition associated with the given \a signal of
+ the given \a sender. The transition has the given \a targets and \a
+ sourceState.
+*/
+QSignalTransition::QSignalTransition(QObject *sender, const char *signal,
+ const QList<QAbstractState*> &targets,
+ QState *sourceState)
+ : QAbstractTransition(*new QSignalTransitionPrivate, targets, sourceState)
+{
+ Q_D(QSignalTransition);
+ d->sender = sender;
+ d->signal = signal;
+}
+
+/*!
+ Destroys this signal transition.
+*/
+QSignalTransition::~QSignalTransition()
+{
+}
+
+/*!
+ Returns the sender object associated with this signal transition.
+*/
+QObject *QSignalTransition::senderObject() const
+{
+ Q_D(const QSignalTransition);
+ return d->sender;
+}
+
+/*!
+ Sets the \a sender object associated with this signal transition.
+*/
+void QSignalTransition::setSenderObject(QObject *sender)
+{
+ Q_D(QSignalTransition);
+ if (sender == d->sender)
+ return;
+ d->sender = sender;
+ d->invalidate();
+}
+
+/*!
+ Returns the signal associated with this signal transition.
+*/
+QByteArray QSignalTransition::signal() const
+{
+ Q_D(const QSignalTransition);
+ return d->signal;
+}
+
+/*!
+ Sets the \a signal associated with this signal transition.
+*/
+void QSignalTransition::setSignal(const QByteArray &signal)
+{
+ Q_D(QSignalTransition);
+ if (signal == d->signal)
+ return;
+ d->signal = signal;
+ d->invalidate();
+}
+
+/*!
+ \reimp
+
+ The \a event is a QSignalEvent object. The default implementation returns
+ true if the event's sender and signal index match this transition, and
+ returns false otherwise.
+*/
+bool QSignalTransition::eventTest(QEvent *event) const
+{
+ Q_D(const QSignalTransition);
+#ifndef QT_STATEMACHINE_SOLUTION
+ if (event->type() == QEvent::Signal) {
+#else
+ if (event->type() == QEvent::Type(QEvent::User-1)) {
+#endif
+ if (d->signalIndex == -1)
+ return false;
+ QSignalEvent *se = static_cast<QSignalEvent*>(event);
+ return (se->sender() == d->sender)
+ && (se->signalIndex() == d->signalIndex);
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QSignalTransition::onTransition(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+bool QSignalTransition::event(QEvent *e)
+{
+ return QAbstractTransition::event(e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h
new file mode 100644
index 0000000..98a9ae7
--- /dev/null
+++ b/src/corelib/statemachine/qsignaltransition.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIGNALTRANSITION_H
+#define QSIGNALTRANSITION_H
+
+#ifndef QT_STATEMACHINE_SOLUTION
+#include <QtCore/qabstracttransition.h>
+#else
+#include "qabstracttransition.h"
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QSignalTransitionPrivate;
+class Q_CORE_EXPORT QSignalTransition : public QAbstractTransition
+{
+ Q_OBJECT
+ Q_PROPERTY(QObject* senderObject READ senderObject WRITE setSenderObject)
+ Q_PROPERTY(QByteArray signal READ signal WRITE setSignal)
+public:
+ QSignalTransition(QState *sourceState = 0);
+ QSignalTransition(QObject *sender, const char *signal,
+ QState *sourceState = 0);
+ QSignalTransition(QObject *sender, const char *signal,
+ const QList<QAbstractState*> &targets,
+ QState *sourceState = 0);
+ ~QSignalTransition();
+
+ QObject *senderObject() const;
+ void setSenderObject(QObject *sender);
+
+ QByteArray signal() const;
+ void setSignal(const QByteArray &signal);
+
+protected:
+ bool eventTest(QEvent *event) const;
+ void onTransition(QEvent *event);
+
+ bool event(QEvent *e);
+
+private:
+ Q_DISABLE_COPY(QSignalTransition)
+ Q_DECLARE_PRIVATE(QSignalTransition)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qsignaltransition_p.h b/src/corelib/statemachine/qsignaltransition_p.h
new file mode 100644
index 0000000..a23e58c
--- /dev/null
+++ b/src/corelib/statemachine/qsignaltransition_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIGNALTRANSITION_P_H
+#define QSIGNALTRANSITION_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 "qabstracttransition_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSignalTransition;
+class QSignalTransitionPrivate : public QAbstractTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QSignalTransition)
+public:
+ QSignalTransitionPrivate();
+
+ static QSignalTransitionPrivate *get(QSignalTransition *q);
+
+ void invalidate();
+
+ QObject *sender;
+ QByteArray signal;
+ int signalIndex;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp
new file mode 100644
index 0000000..4c9e033
--- /dev/null
+++ b/src/corelib/statemachine/qstate.cpp
@@ -0,0 +1,481 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstate.h"
+#include "qstate_p.h"
+#include "qhistorystate.h"
+#include "qhistorystate_p.h"
+#include "qabstracttransition.h"
+#include "qabstracttransition_p.h"
+#include "qsignaltransition.h"
+#include "qstatemachine.h"
+#include "qstatemachine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QState
+
+ \brief The QState class provides a general-purpose state for QStateMachine.
+
+ \since 4.6
+ \ingroup statemachine
+
+ QState objects can have child states, and can have transitions to other
+ states. QState is part of \l{The State Machine Framework}.
+
+ The addTransition() function adds a transition. The removeTransition()
+ function removes a transition.
+
+ The assignProperty() function is used for defining property assignments that
+ should be performed when a state is entered.
+
+ Top-level states must be passed QStateMachine::rootState() as their parent
+ state, or added to a state machine using QStateMachine::addState().
+
+ \section1 States with Child States
+
+ The childMode property determines how child states are treated. For
+ non-parallel state groups, the setInitialState() function must be called to
+ set the initial state. The child states are mutually exclusive states, and
+ the state machine needs to know which child state to enter when the parent
+ state is the target of a transition.
+
+ The state emits the QState::finished() signal when a final child state
+ (QFinalState) is entered.
+
+ The setErrorState() sets the state's error state. The error state is the
+ state that the state machine will transition to if an error is detected when
+ attempting to enter the state (e.g. because no initial state has been set).
+
+*/
+
+/*!
+ \property QState::initialState
+
+ \brief the initial state of this state (one of its child states)
+*/
+
+/*!
+ \property QState::errorState
+
+ \brief the error state of this state
+*/
+
+/*!
+ \property QState::childMode
+
+ \brief the child mode of this state
+
+ The default value of this property is QState::ExclusiveStates.
+*/
+
+/*!
+ \enum QState::ChildMode
+
+ This enum specifies how a state's child states are treated.
+
+ \value ExclusiveStates The child states are mutually exclusive and an
+ initial state must be set by calling QState::setInitialState().
+
+ \value ParallelStates The child states are parallel. When the parent state
+ is entered, all its child states are entered in parallel.
+*/
+
+QStatePrivate::QStatePrivate()
+ : errorState(0), initialState(0), childMode(QState::ExclusiveStates)
+{
+}
+
+QStatePrivate::~QStatePrivate()
+{
+}
+
+QStatePrivate *QStatePrivate::get(QState *q)
+{
+ if (!q)
+ return 0;
+ return q->d_func();
+}
+
+const QStatePrivate *QStatePrivate::get(const QState *q)
+{
+ if (!q)
+ return 0;
+ return q->d_func();
+}
+
+void QStatePrivate::emitFinished()
+{
+ Q_Q(QState);
+ emit q->finished();
+}
+
+void QStatePrivate::emitPolished()
+{
+ Q_Q(QState);
+ emit q->polished();
+}
+
+/*!
+ Constructs a new state with the given \a parent state.
+*/
+QState::QState(QState *parent)
+ : QAbstractState(*new QStatePrivate, parent)
+{
+}
+
+/*!
+ Constructs a new state with the given \a childMode and the given \a parent
+ state.
+*/
+QState::QState(ChildMode childMode, QState *parent)
+ : QAbstractState(*new QStatePrivate, parent)
+{
+ Q_D(QState);
+ d->childMode = childMode;
+}
+
+/*!
+ \internal
+*/
+QState::QState(QStatePrivate &dd, QState *parent)
+ : QAbstractState(dd, parent)
+{
+}
+
+/*!
+ Destroys this state.
+*/
+QState::~QState()
+{
+}
+
+QList<QAbstractState*> QStatePrivate::childStates() const
+{
+ QList<QAbstractState*> result;
+ QList<QObject*>::const_iterator it;
+#ifdef QT_STATEMACHINE_SOLUTION
+ const QObjectList &children = q_func()->children();
+#endif
+ for (it = children.constBegin(); it != children.constEnd(); ++it) {
+ QAbstractState *s = qobject_cast<QAbstractState*>(*it);
+ if (!s || qobject_cast<QHistoryState*>(s))
+ continue;
+ result.append(s);
+ }
+ return result;
+}
+
+QList<QHistoryState*> QStatePrivate::historyStates() const
+{
+ QList<QHistoryState*> result;
+ QList<QObject*>::const_iterator it;
+#ifdef QT_STATEMACHINE_SOLUTION
+ const QObjectList &children = q_func()->children();
+#endif
+ for (it = children.constBegin(); it != children.constEnd(); ++it) {
+ QHistoryState *h = qobject_cast<QHistoryState*>(*it);
+ if (h)
+ result.append(h);
+ }
+ return result;
+}
+
+QList<QAbstractTransition*> QStatePrivate::transitions() const
+{
+ QList<QAbstractTransition*> result;
+ QList<QObject*>::const_iterator it;
+#ifdef QT_STATEMACHINE_SOLUTION
+ const QObjectList &children = q_func()->children();
+#endif
+ for (it = children.constBegin(); it != children.constEnd(); ++it) {
+ QAbstractTransition *t = qobject_cast<QAbstractTransition*>(*it);
+ if (t)
+ result.append(t);
+ }
+ return result;
+}
+
+/*!
+ Instructs this state to set the property with the given \a name of the given
+ \a object to the given \a value when the state is entered.
+
+ \sa polished()
+*/
+void QState::assignProperty(QObject *object, const char *name,
+ const QVariant &value)
+{
+ Q_D(QState);
+ if (!object) {
+ qWarning("QState::assignProperty: cannot assign property '%s' of null object", name);
+ return;
+ }
+ for (int i = 0; i < d->propertyAssignments.size(); ++i) {
+ QPropertyAssignment &assn = d->propertyAssignments[i];
+ if ((assn.object == object) && (assn.propertyName == name)) {
+ assn.value = value;
+ return;
+ }
+ }
+ d->propertyAssignments.append(QPropertyAssignment(object, name, value));
+}
+
+/*!
+ Returns this state group's error state.
+
+ \sa QStateMachine::errorState(), QStateMachine::setErrorState()
+*/
+QAbstractState *QState::errorState() const
+{
+ Q_D(const QState);
+ return d->errorState;
+}
+
+/*!
+ Sets this state's error state to be the given \a state. If the error state
+ is not set, or if it is set to 0, the state will inherit its parent's error
+ state recursively.
+
+ \sa QStateMachine::setErrorState(), QStateMachine::errorState()
+*/
+void QState::setErrorState(QAbstractState *state)
+{
+ Q_D(QState);
+ if (state != 0 && QAbstractStatePrivate::get(state)->machine() != d->machine()) {
+ qWarning("QState::setErrorState: error state cannot belong "
+ "to a different state machine");
+ return;
+ }
+
+ d->errorState = state;
+}
+
+/*!
+ Adds the given \a transition. The transition has this state as the source.
+ This state takes ownership of the transition. If the transition is successfully
+ added, the function will return the \a transition pointer. Otherwise it will return null.
+*/
+QAbstractTransition *QState::addTransition(QAbstractTransition *transition)
+{
+ Q_D(QState);
+ if (!transition) {
+ qWarning("QState::addTransition: cannot add null transition");
+ return 0;
+ }
+ const QList<QAbstractState*> &targets = QAbstractTransitionPrivate::get(transition)->targetStates;
+ for (int i = 0; i < targets.size(); ++i) {
+ QAbstractState *t = targets.at(i);
+ if (!t) {
+ qWarning("QState::addTransition: cannot add transition to null state");
+ return 0;
+ }
+ if ((QAbstractStatePrivate::get(t)->machine() != d->machine())
+ && QAbstractStatePrivate::get(t)->machine() && d->machine()) {
+ qWarning("QState::addTransition: cannot add transition "
+ "to a state in a different state machine");
+ return 0;
+ }
+ }
+ transition->setParent(this);
+ return transition;
+}
+
+/*!
+ Adds a transition associated with the given \a signal of the given \a sender
+ object, and returns the new QSignalTransition object. The transition has
+ this state as the source, and the given \a target as the target state.
+*/
+QSignalTransition *QState::addTransition(QObject *sender, const char *signal,
+ QAbstractState *target)
+{
+ if (!sender) {
+ qWarning("QState::addTransition: sender cannot be null");
+ return 0;
+ }
+ if (!signal) {
+ qWarning("QState::addTransition: signal cannot be null");
+ return 0;
+ }
+ QSignalTransition *trans = new QSignalTransition(sender, signal, QList<QAbstractState*>() << target);
+ addTransition(trans);
+ return trans;
+}
+
+namespace {
+
+// ### Make public?
+class UnconditionalTransition : public QAbstractTransition
+{
+public:
+ UnconditionalTransition(QAbstractState *target)
+ : QAbstractTransition(QList<QAbstractState*>() << target) {}
+protected:
+ void onTransition(QEvent *) {}
+ bool eventTest(QEvent *) const { return true; }
+};
+
+} // namespace
+
+/*!
+ Adds an unconditional transition from this state to the given \a target
+ state, and returns then new transition object.
+*/
+QAbstractTransition *QState::addTransition(QAbstractState *target)
+{
+ UnconditionalTransition *trans = new UnconditionalTransition(target);
+ addTransition(trans);
+ return trans;
+}
+
+/*!
+ Removes the given \a transition from this state. The state releases
+ ownership of the transition.
+
+ \sa addTransition()
+*/
+void QState::removeTransition(QAbstractTransition *transition)
+{
+ Q_D(QState);
+ if (!transition) {
+ qWarning("QState::removeTransition: cannot remove null transition");
+ return;
+ }
+ if (transition->sourceState() != this) {
+ qWarning("QState::removeTransition: transition %p's source state (%p)"
+ " is different from this state (%p)",
+ transition, transition->sourceState(), this);
+ return;
+ }
+ QStateMachinePrivate *mach = QStateMachinePrivate::get(d->machine());
+ if (mach)
+ mach->unregisterTransition(transition);
+ transition->setParent(0);
+}
+
+/*!
+ \reimp
+*/
+void QState::onEntry(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+void QState::onExit(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ Returns this state's initial state, or 0 if the state has no initial state.
+*/
+QAbstractState *QState::initialState() const
+{
+ Q_D(const QState);
+ return d->initialState;
+}
+
+/*!
+ Sets this state's initial state to be the given \a state.
+ \a state has to be a child of this state.
+*/
+void QState::setInitialState(QAbstractState *state)
+{
+ Q_D(QState);
+ if (d->childMode == QState::ParallelStates) {
+ qWarning("QState::setInitialState: ignoring attempt to set initial state "
+ "of parallel state group %p", this);
+ return;
+ }
+ if (state && (state->parentState() != this)) {
+ qWarning("QState::setInitialState: state %p is not a child of this state (%p)",
+ state, this);
+ return;
+ }
+ d->initialState = state;
+}
+
+/*!
+ Returns the child mode of this state.
+*/
+QState::ChildMode QState::childMode() const
+{
+ Q_D(const QState);
+ return d->childMode;
+}
+
+/*!
+ Sets the child \a mode of this state.
+*/
+void QState::setChildMode(ChildMode mode)
+{
+ Q_D(QState);
+ d->childMode = mode;
+}
+
+/*!
+ \reimp
+*/
+bool QState::event(QEvent *e)
+{
+ return QAbstractState::event(e);
+}
+
+/*!
+ \fn QState::finished()
+
+ This signal is emitted when a final child state of this state is entered.
+
+ \sa QFinalState
+*/
+
+/*!
+ \fn QState::polished()
+
+ This signal is emitted when all properties have been assigned their final value.
+
+ \sa QState::assignProperty(), QAbstractTransition::addAnimation()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h
new file mode 100644
index 0000000..73955d7
--- /dev/null
+++ b/src/corelib/statemachine/qstate.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATE_H
+#define QSTATE_H
+
+#ifndef QT_STATEMACHINE_SOLUTION
+#include <QtCore/qabstractstate.h>
+#else
+#include "qabstractstate.h"
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QAbstractTransition;
+class QSignalTransition;
+
+class QStatePrivate;
+class Q_CORE_EXPORT QState : public QAbstractState
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState)
+ Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState)
+ Q_PROPERTY(ChildMode childMode READ childMode WRITE setChildMode)
+ Q_ENUMS(ChildMode)
+public:
+ enum ChildMode {
+ ExclusiveStates,
+ ParallelStates
+ };
+
+ QState(QState *parent = 0);
+ QState(ChildMode childMode, QState *parent = 0);
+ ~QState();
+
+ QAbstractState *errorState() const;
+ void setErrorState(QAbstractState *state);
+
+ QAbstractTransition *addTransition(QAbstractTransition *transition);
+ QSignalTransition *addTransition(QObject *sender, const char *signal, QAbstractState *target);
+ QAbstractTransition *addTransition(QAbstractState *target);
+ void removeTransition(QAbstractTransition *transition);
+
+ QAbstractState *initialState() const;
+ void setInitialState(QAbstractState *state);
+
+ ChildMode childMode() const;
+ void setChildMode(ChildMode mode);
+
+ void assignProperty(QObject *object, const char *name,
+ const QVariant &value);
+
+Q_SIGNALS:
+ void finished();
+ void polished();
+
+protected:
+ void onEntry(QEvent *event);
+ void onExit(QEvent *event);
+
+ bool event(QEvent *e);
+
+protected:
+ QState(QStatePrivate &dd, QState *parent);
+
+private:
+ Q_DISABLE_COPY(QState)
+ Q_DECLARE_PRIVATE(QState)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h
new file mode 100644
index 0000000..1f913b4
--- /dev/null
+++ b/src/corelib/statemachine/qstate_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATE_P_H
+#define QSTATE_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 "qabstractstate_p.h"
+
+#include <QtCore/qlist.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QPropertyAssignment
+{
+ QPropertyAssignment()
+ : object(0) {}
+ QPropertyAssignment(QObject *o, const QByteArray &n,
+ const QVariant &v, bool es = true)
+ : object(o), propertyName(n), value(v), explicitlySet(es)
+ {}
+ QObject *object;
+ QByteArray propertyName;
+ QVariant value;
+ bool explicitlySet;
+};
+
+class QAbstractTransition;
+class QHistoryState;
+
+class QState;
+class Q_CORE_EXPORT QStatePrivate : public QAbstractStatePrivate
+{
+ Q_DECLARE_PUBLIC(QState)
+public:
+ QStatePrivate();
+ ~QStatePrivate();
+
+ static QStatePrivate *get(QState *q);
+ static const QStatePrivate *get(const QState *q);
+
+ QList<QAbstractState*> childStates() const;
+ QList<QHistoryState*> historyStates() const;
+ QList<QAbstractTransition*> transitions() const;
+
+ void emitFinished();
+ void emitPolished();
+
+ QAbstractState *errorState;
+ QAbstractState *initialState;
+ QState::ChildMode childMode;
+
+ QList<QPropertyAssignment> propertyAssignments;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
new file mode 100644
index 0000000..21e564c
--- /dev/null
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -0,0 +1,2218 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstatemachine.h"
+#include "qstate.h"
+#include "qstate_p.h"
+#include "qstatemachine_p.h"
+#include "qabstracttransition.h"
+#include "qabstracttransition_p.h"
+#include "qsignaltransition.h"
+#include "qsignaltransition_p.h"
+#include "qsignalevent.h"
+#include "qsignaleventgenerator_p.h"
+#include "qabstractstate.h"
+#include "qabstractstate_p.h"
+#include "qfinalstate.h"
+#include "qhistorystate.h"
+#include "qhistorystate_p.h"
+#ifndef QT_STATEMACHINE_SOLUTION
+#include "private/qobject_p.h"
+#include "private/qthread_p.h"
+#endif
+
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+#include "qeventtransition.h"
+#include "qeventtransition_p.h"
+#include "qwrappedevent.h"
+#endif
+
+#ifndef QT_NO_ANIMATION
+#include "qpropertyanimation.h"
+#include "qanimationgroup.h"
+# ifndef QT_STATEMACHINE_SOLUTION
+# include <private/qvariantanimation_p.h>
+# else
+# include "qvariantanimation_p.h"
+# endif
+#endif
+
+#include <QtCore/qmetaobject.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QStateMachine
+ \reentrant
+
+ \brief The QStateMachine class provides a hierarchical finite state machine.
+
+ \since 4.6
+ \ingroup statemachine
+
+ The QStateMachine class provides a hierarchical finite state machine based
+ on \l{Statecharts: A visual formalism for complex systems}{Statecharts}
+ concepts and notation. QStateMachine is part of \l{The State Machine
+ Framework}.
+
+ A state machine manages a set of states (QAbstractState objects) and
+ transitions (QAbstractTransition objects) between those states; the states
+ and the transitions collectively define a state graph. Once a state graph
+ has been defined, the state machine can execute it. QStateMachine's
+ execution algorithm is based on the \l{State Chart XML: State Machine
+ Notation for Control Abstraction}{State Chart XML (SCXML)} algorithm.
+
+ The QState class provides a state that you can use to set properties and
+ invoke methods on QObjects when the state is entered or exited. This is
+ typically used in conjunction with \l{Signals and Slots}{signals}; the
+ signals determine the flow of the state graph, whereas the states' property
+ assignments and method invocations are the actions.
+
+ Use the addState() function to add a state to the state machine;
+ alternatively, pass the machine's rootState() to the state constructor. Use
+ the removeState() function to remove a state from the state machine.
+
+ The following snippet shows a state machine that will finish when a button
+ is clicked:
+
+ \code
+ QPushButton button;
+
+ QStateMachine machine;
+ QState *s1 = new QState();
+ s1->assignProperty(&button, "text", "Click me");
+
+ QFinalState *s2 = new QFinalState();
+ s1->addTransition(&button, SIGNAL(clicked()), s2);
+
+ machine.addState(s1);
+ machine.addState(s2);
+ machine.setInitialState(s1);
+ machine.start();
+ \endcode
+
+ The setInitialState() function sets the state machine's initial state; this
+ state is entered when the state machine is started.
+
+ The start() function starts the state machine. The state machine executes
+ asynchronously, i.e. you need to run an event loop in order for it to make
+ progress. The started() signal is emitted when the state machine has entered
+ the initial state.
+
+ The state machine processes events and takes transitions until a top-level
+ final state is entered; the state machine then emits the finished() signal.
+
+ The stop() function stops the state machine. The stopped() signal is emitted
+ when the state machine has stopped.
+
+ The postEvent() function posts an event to the state machine. This is useful
+ when you are using custom events to trigger transitions.
+
+ The rootState() function returns the state machine's root state. All
+ top-level states have the root state as their parent.
+
+ \sa QAbstractState, QAbstractTransition
+*/
+
+/*!
+ \property QStateMachine::rootState
+
+ \brief the root state of this state machine
+*/
+
+/*!
+ \property QStateMachine::initialState
+
+ \brief the initial state of this state machine
+
+ The initial state must be one of the rootState()'s child states.
+*/
+
+/*!
+ \property QStateMachine::errorState
+
+ \brief the error state of this state machine
+*/
+
+/*!
+ \property QStateMachine::errorString
+
+ \brief the error string of this state machine
+*/
+
+/*!
+ \property QStateMachine::globalRestorePolicy
+
+ \brief the restore policy for states of this state machine.
+
+ The default value of this property is
+ QStateMachine::DoNotRestoreProperties.
+*/
+
+#ifndef QT_NO_ANIMATION
+/*!
+ \property QStateMachine::animationsEnabled
+
+ \brief whether animations are enabled
+
+ The default value of this property is true.
+
+ \sa QAbstractTransition::addAnimation()
+*/
+#endif
+
+// #define QSTATEMACHINE_DEBUG
+
+QStateMachinePrivate::QStateMachinePrivate()
+{
+ state = NotRunning;
+ processing = false;
+ processingScheduled = false;
+ stop = false;
+ error = QStateMachine::NoError;
+ globalRestorePolicy = QStateMachine::DoNotRestoreProperties;
+ rootState = 0;
+ initialErrorStateForRoot = 0;
+#ifndef QT_STATEMACHINE_SOLUTION
+ signalEventGenerator = 0;
+#endif
+#ifndef QT_NO_ANIMATION
+ animationsEnabled = true;
+#endif
+}
+
+QStateMachinePrivate::~QStateMachinePrivate()
+{
+ qDeleteAll(internalEventQueue);
+ qDeleteAll(externalEventQueue);
+}
+
+QStateMachinePrivate *QStateMachinePrivate::get(QStateMachine *q)
+{
+ if (q)
+ return q->d_func();
+ return 0;
+}
+
+static QEvent *cloneEvent(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::None:
+ return new QEvent(*e);
+ case QEvent::Timer:
+ return new QTimerEvent(*static_cast<QTimerEvent*>(e));
+ default:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ }
+ return 0;
+}
+
+const QStateMachinePrivate::Handler qt_kernel_statemachine_handler = {
+ cloneEvent
+};
+
+const QStateMachinePrivate::Handler *QStateMachinePrivate::handler = &qt_kernel_statemachine_handler;
+
+Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler()
+{
+ return &qt_kernel_statemachine_handler;
+}
+
+static int indexOfDescendant(QState *s, QAbstractState *desc)
+{
+ QList<QAbstractState*> childStates = QStatePrivate::get(s)->childStates();
+ for (int i = 0; i < childStates.size(); ++i) {
+ QAbstractState *c = childStates.at(i);
+ if ((c == desc) || QStateMachinePrivate::isDescendantOf(desc, c)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState *s2)
+{
+ if (s1->parent() == s2->parent()) {
+ return s1->children().indexOf(s1)
+ < s2->children().indexOf(s2);
+ } else if (isDescendantOf(s1, s2)) {
+ return false;
+ } else if (isDescendantOf(s2, s1)) {
+ return true;
+ } else {
+ QState *lca = findLCA(QList<QAbstractState*>() << s1 << s2);
+ Q_ASSERT(lca != 0);
+ return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
+ }
+}
+
+bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState *s2)
+{
+ if (s1->parent() == s2->parent()) {
+ return s1->children().indexOf(s1)
+ < s2->children().indexOf(s2);
+ } else if (isDescendantOf(s1, s2)) {
+ return true;
+ } else if (isDescendantOf(s2, s1)) {
+ return false;
+ } else {
+ QState *lca = findLCA(QList<QAbstractState*>() << s1 << s2);
+ Q_ASSERT(lca != 0);
+ return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
+ }
+}
+
+QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states)
+{
+ if (states.isEmpty())
+ return 0;
+ QList<QState*> ancestors = properAncestors(states.at(0), 0);
+ for (int i = 0; i < ancestors.size(); ++i) {
+ QState *anc = ancestors.at(i);
+ bool ok = true;
+ for (int j = states.size() - 1; (j > 0) && ok; --j) {
+ const QAbstractState *s = states.at(j);
+ if (!isDescendantOf(s, anc))
+ ok = false;
+ }
+ if (ok)
+ return anc;
+ }
+ return 0;
+}
+
+bool QStateMachinePrivate::isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const
+{
+ QSet<QAbstractTransition*>::const_iterator it;
+ for (it = transitions.constBegin(); it != transitions.constEnd(); ++it) {
+ QAbstractTransition *t = *it;
+ QList<QAbstractState*> lst = t->targetStates();
+ if (!lst.isEmpty()) {
+ lst.prepend(t->sourceState());
+ QAbstractState *lca = findLCA(lst);
+ if (isDescendantOf(s, lca)) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ":" << transitions << "preempts selection of a transition from"
+ << s << "because" << s << "is a descendant of" << lca;
+#endif
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+QSet<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event) const
+{
+ Q_Q(const QStateMachine);
+ QSet<QAbstractTransition*> enabledTransitions;
+ QSet<QAbstractState*>::const_iterator it;
+ const_cast<QStateMachine*>(q)->beginSelectTransitions(event);
+ for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
+ QAbstractState *state = *it;
+ if (!isAtomic(state))
+ continue;
+ if (isPreempted(state, enabledTransitions))
+ continue;
+ QList<QState*> lst = properAncestors(state, 0);
+ if (QState *grp = qobject_cast<QState*>(state))
+ lst.prepend(grp);
+ bool found = false;
+ for (int j = 0; (j < lst.size()) && !found; ++j) {
+ QState *s = lst.at(j);
+ QList<QAbstractTransition*> transitions = QStatePrivate::get(s)->transitions();
+ for (int k = 0; k < transitions.size(); ++k) {
+ QAbstractTransition *t = transitions.at(k);
+ if (QAbstractTransitionPrivate::get(t)->callEventTest(event)) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": selecting transition" << t;
+#endif
+ enabledTransitions.insert(t);
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ const_cast<QStateMachine*>(q)->endSelectTransitions(event);
+ return enabledTransitions;
+}
+
+void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
+{
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ")";
+ qDebug() << q_func() << ": configuration before exiting states:" << configuration;
+#endif
+ QList<QAbstractState*> exitedStates = exitStates(event, enabledTransitions);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": configuration after exiting states:" << configuration;
+#endif
+ executeTransitionContent(event, enabledTransitions);
+ QList<QAbstractState*> enteredStates = enterStates(event, enabledTransitions);
+ applyProperties(enabledTransitions, exitedStates, enteredStates);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": configuration after entering states:" << configuration;
+ qDebug() << q_func() << ": end microstep";
+#endif
+}
+
+QList<QAbstractState*> QStateMachinePrivate::exitStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
+{
+// qDebug() << "exitStates(" << enabledTransitions << ")";
+ QSet<QAbstractState*> statesToExit;
+// QSet<QAbstractState*> statesToSnapshot;
+ for (int i = 0; i < enabledTransitions.size(); ++i) {
+ QAbstractTransition *t = enabledTransitions.at(i);
+ QList<QAbstractState*> lst = t->targetStates();
+ if (lst.isEmpty())
+ continue;
+ lst.prepend(t->sourceState());
+ QAbstractState *lca = findLCA(lst);
+ if (lca == 0) {
+ setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState());
+ lst = pendingErrorStates.toList();
+ lst.prepend(t->sourceState());
+
+ lca = findLCA(lst);
+ Q_ASSERT(lca != 0);
+ }
+
+ {
+ QSet<QAbstractState*>::const_iterator it;
+ for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
+ QAbstractState *s = *it;
+ if (isDescendantOf(s, lca))
+ statesToExit.insert(s);
+ }
+ }
+ }
+ QList<QAbstractState*> statesToExit_sorted = statesToExit.toList();
+ qSort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
+ for (int i = 0; i < statesToExit_sorted.size(); ++i) {
+ QAbstractState *s = statesToExit_sorted.at(i);
+ if (QState *grp = qobject_cast<QState*>(s)) {
+ QList<QHistoryState*> hlst = QStatePrivate::get(grp)->historyStates();
+ for (int j = 0; j < hlst.size(); ++j) {
+ QHistoryState *h = hlst.at(j);
+ QHistoryStatePrivate::get(h)->configuration.clear();
+ QSet<QAbstractState*>::const_iterator it;
+ for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
+ QAbstractState *s0 = *it;
+ if (QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) {
+ if (isAtomic(s0) && isDescendantOf(s0, s))
+ QHistoryStatePrivate::get(h)->configuration.append(s0);
+ } else if (s0->parentState() == s) {
+ QHistoryStatePrivate::get(h)->configuration.append(s0);
+ }
+ }
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": recorded" << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow")
+ << "history for" << s << "in" << h << ":" << QHistoryStatePrivate::get(h)->configuration;
+#endif
+ }
+ }
+ }
+ for (int i = 0; i < statesToExit_sorted.size(); ++i) {
+ QAbstractState *s = statesToExit_sorted.at(i);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": exiting" << s;
+#endif
+ QAbstractStatePrivate::get(s)->callOnExit(event);
+ configuration.remove(s);
+ QAbstractStatePrivate::get(s)->emitExited();
+ }
+ return statesToExit_sorted;
+}
+
+void QStateMachinePrivate::executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
+{
+ for (int i = 0; i < enabledTransitions.size(); ++i) {
+ QAbstractTransition *t = enabledTransitions.at(i);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": triggering" << t;
+#endif
+ QAbstractTransitionPrivate::get(t)->callOnTransition(event);
+ }
+}
+
+QList<QAbstractState*> QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
+{
+#ifdef QSTATEMACHINE_DEBUG
+ Q_Q(QStateMachine);
+#endif
+// qDebug() << "enterStates(" << enabledTransitions << ")";
+ QSet<QAbstractState*> statesToEnter;
+ QSet<QAbstractState*> statesForDefaultEntry;
+
+ if (pendingErrorStates.isEmpty()) {
+ for (int i = 0; i < enabledTransitions.size(); ++i) {
+ QAbstractTransition *t = enabledTransitions.at(i);
+ QList<QAbstractState*> lst = t->targetStates();
+ if (lst.isEmpty())
+ continue;
+ lst.prepend(t->sourceState());
+ QState *lca = findLCA(lst);
+ for (int j = 1; j < lst.size(); ++j) {
+ QAbstractState *s = lst.at(j);
+ addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry);
+ if (isParallel(lca)) {
+ QList<QAbstractState*> lcac = QStatePrivate::get(lca)->childStates();
+ foreach (QAbstractState* child,lcac) {
+ if (!statesToEnter.contains(child))
+ addStatesToEnter(child,lca,statesToEnter,statesForDefaultEntry);
+ }
+ }
+ }
+ }
+ }
+
+ // Did an error occur while selecting transitions? Then we enter the error state.
+ if (!pendingErrorStates.isEmpty()) {
+ statesToEnter.clear();
+ statesToEnter = pendingErrorStates;
+ statesForDefaultEntry = pendingErrorStatesForDefaultEntry;
+ pendingErrorStates.clear();
+ pendingErrorStatesForDefaultEntry.clear();
+ }
+
+ QList<QAbstractState*> statesToEnter_sorted = statesToEnter.toList();
+ qSort(statesToEnter_sorted.begin(), statesToEnter_sorted.end(), stateEntryLessThan);
+
+ for (int i = 0; i < statesToEnter_sorted.size(); ++i) {
+ QAbstractState *s = statesToEnter_sorted.at(i);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": entering" << s;
+#endif
+ configuration.insert(s);
+ registerTransitions(s);
+ QAbstractStatePrivate::get(s)->callOnEntry(event);
+ QAbstractStatePrivate::get(s)->emitEntered();
+ if (statesForDefaultEntry.contains(s)) {
+ // ### executeContent(s.initial.transition.children())
+ }
+ if (isFinal(s)) {
+ QState *parent = s->parentState();
+ if (parent) {
+ QState *grandparent = parent->parentState();
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": emitting finished signal for" << parent;
+#endif
+ QStatePrivate::get(parent)->emitFinished();
+ if (grandparent && isParallel(grandparent)) {
+ bool allChildStatesFinal = true;
+ QList<QAbstractState*> childStates = QStatePrivate::get(grandparent)->childStates();
+ for (int j = 0; j < childStates.size(); ++j) {
+ QAbstractState *cs = childStates.at(j);
+ if (!isInFinalState(cs)) {
+ allChildStatesFinal = false;
+ break;
+ }
+ }
+ if (allChildStatesFinal) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": emitting finished signal for" << grandparent;
+#endif
+ QStatePrivate::get(grandparent)->emitFinished();
+ }
+ }
+ }
+ }
+ }
+ {
+ QSet<QAbstractState*>::const_iterator it;
+ for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
+ if (isFinal(*it) && (*it)->parentState() == rootState) {
+ processing = false;
+ stopProcessingReason = Finished;
+ break;
+ }
+ }
+ }
+// qDebug() << "configuration:" << configuration.toList();
+ return statesToEnter_sorted;
+}
+
+void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root,
+ QSet<QAbstractState*> &statesToEnter,
+ QSet<QAbstractState*> &statesForDefaultEntry)
+{
+ if (QHistoryState *h = qobject_cast<QHistoryState*>(s)) {
+ QList<QAbstractState*> hconf = QHistoryStatePrivate::get(h)->configuration;
+ if (!hconf.isEmpty()) {
+ for (int k = 0; k < hconf.size(); ++k) {
+ QAbstractState *s0 = hconf.at(k);
+ addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry);
+ }
+ #ifdef QSTATEMACHINE_DEBUG
+ qDebug() <<q_func() << ": restoring"
+ << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow")
+ << "history from" << s << ":" << hconf;
+ #endif
+ } else {
+ QList<QAbstractState*> hlst;
+ if (QHistoryStatePrivate::get(h)->defaultState)
+ hlst.append(QHistoryStatePrivate::get(h)->defaultState);
+
+ if (hlst.isEmpty()) {
+ setError(QStateMachine::NoDefaultStateInHistoryStateError, h);
+ } else {
+ for (int k = 0; k < hlst.size(); ++k) {
+ QAbstractState *s0 = hlst.at(k);
+ addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry);
+ }
+ #ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": initial history targets for" << s << ":" << hlst;
+ #endif
+ }
+ }
+ } else {
+ statesToEnter.insert(s);
+ if (isParallel(s)) {
+ QState *grp = qobject_cast<QState*>(s);
+ QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
+ for (int i = 0; i < lst.size(); ++i) {
+ QAbstractState *child = lst.at(i);
+ addStatesToEnter(child, grp, statesToEnter, statesForDefaultEntry);
+ }
+ } else if (isCompound(s)) {
+ statesForDefaultEntry.insert(s);
+ QState *grp = qobject_cast<QState*>(s);
+ QAbstractState *initial = grp->initialState();
+ if (initial != 0) {
+ addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry);
+ } else {
+ setError(QStateMachine::NoInitialStateError, grp);
+ return;
+ }
+ }
+ QList<QState*> ancs = properAncestors(s, root);
+ for (int i = 0; i < ancs.size(); ++i) {
+ QState *anc = ancs.at(i);
+ if (!anc->parentState())
+ continue;
+ statesToEnter.insert(anc);
+ if (isParallel(anc)) {
+ QList<QAbstractState*> lst = QStatePrivate::get(anc)->childStates();
+ for (int j = 0; j < lst.size(); ++j) {
+ QAbstractState *child = lst.at(j);
+ bool hasDescendantInList = false;
+ QSet<QAbstractState*>::const_iterator it;
+ for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) {
+ if (isDescendantOf(*it, child)) {
+ hasDescendantInList = true;
+ break;
+ }
+ }
+ if (!hasDescendantInList)
+ addStatesToEnter(child, anc, statesToEnter, statesForDefaultEntry);
+ }
+ }
+ }
+ }
+}
+
+void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &transitionList,
+ const QList<QAbstractState*> &exitedStates,
+ const QList<QAbstractState*> &enteredStates)
+{
+ Q_Q(QStateMachine);
+#ifdef QT_NO_ANIMATION
+ Q_UNUSED(transitionList);
+#endif
+ // Process the property assignments of the entered states.
+ QHash<QAbstractState*, QList<QPropertyAssignment> > propertyAssignmentsForState;
+ QHash<RestorableId, QVariant> pendingRestorables = registeredRestorables;
+ for (int i = 0; i < enteredStates.size(); ++i) {
+ QState *s = qobject_cast<QState*>(enteredStates.at(i));
+ if (!s)
+ continue;
+
+ QList<QPropertyAssignment> assignments = QStatePrivate::get(s)->propertyAssignments;
+ for (int j = 0; j < assignments.size(); ++j) {
+ const QPropertyAssignment &assn = assignments.at(j);
+ if (globalRestorePolicy == QStateMachine::RestoreProperties) {
+ registerRestorable(assn.object, assn.propertyName);
+ }
+ pendingRestorables.remove(RestorableId(assn.object, assn.propertyName));
+ propertyAssignmentsForState[s].append(assn);
+ }
+
+ // Remove pending restorables for all parent states to avoid restoring properties
+ // before the state that assigned them is exited. If state does not explicitly
+ // assign a property which is assigned by the parent, it inherits the parent's assignment.
+ QState *parentState = s;
+ while ((parentState = parentState->parentState()) != 0) {
+ assignments = QStatePrivate::get(parentState)->propertyAssignments;
+ for (int j=0; j<assignments.size(); ++j) {
+ const QPropertyAssignment &assn = assignments.at(j);
+ int c = pendingRestorables.remove(RestorableId(assn.object, assn.propertyName));
+ if (c > 0)
+ propertyAssignmentsForState[s].append(assn);
+ }
+ }
+ }
+ if (!pendingRestorables.isEmpty()) {
+ QAbstractState *s;
+ if (!enteredStates.isEmpty())
+ s = enteredStates.last(); // ### handle if parallel
+ else
+ s = 0;
+ propertyAssignmentsForState[s] << restorablesToPropertyList(pendingRestorables);
+ }
+
+#ifndef QT_NO_ANIMATION
+ // Gracefully terminate playing animations for states that are exited.
+ for (int i = 0; i < exitedStates.size(); ++i) {
+ QAbstractState *s = exitedStates.at(i);
+ QList<QAbstractAnimation*> animations = animationsForState.take(s);
+ for (int j = 0; j < animations.size(); ++j) {
+ QAbstractAnimation *anim = animations.at(j);
+ QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
+ stateForAnimation.remove(anim);
+
+ // Stop the (top-level) animation.
+ // ### Stopping nested animation has weird behavior.
+ QAbstractAnimation *topLevelAnim = anim;
+ while (QAnimationGroup *group = topLevelAnim->group())
+ topLevelAnim = group;
+ topLevelAnim->stop();
+
+ if (resetAnimationEndValues.contains(anim)) {
+ qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize
+ resetAnimationEndValues.remove(anim);
+ }
+ QPropertyAssignment assn = propertyForAnimation.take(anim);
+ Q_ASSERT(assn.object != 0);
+ // If there is no property assignment that sets this property,
+ // set the property to its target value.
+ bool found = false;
+ QHash<QAbstractState*, QList<QPropertyAssignment> >::const_iterator it;
+ for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) {
+ const QList<QPropertyAssignment> &assignments = it.value();
+ for (int k = 0; k < assignments.size(); ++k) {
+ if ((assignments.at(k).object == assn.object)
+ && (assignments.at(k).propertyName == assn.propertyName)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ assn.object->setProperty(assn.propertyName, assn.value);
+ }
+ }
+ }
+
+ // Find the animations to use for the state change.
+ QList<QAbstractAnimation*> selectedAnimations;
+ if (animationsEnabled) {
+ for (int i = 0; i < transitionList.size(); ++i) {
+ QAbstractTransition *transition = transitionList.at(i);
+
+ selectedAnimations << transition->animations();
+ selectedAnimations << defaultAnimationsForSource.values(transition->sourceState());
+
+ QList<QAbstractState *> targetStates = transition->targetStates();
+ for (int j=0; j<targetStates.size(); ++j)
+ selectedAnimations << defaultAnimationsForTarget.values(targetStates.at(j));
+ }
+ selectedAnimations << defaultAnimations;
+ }
+
+ // Initialize animations from property assignments.
+ for (int i = 0; i < selectedAnimations.size(); ++i) {
+ QAbstractAnimation *anim = selectedAnimations.at(i);
+ QHash<QAbstractState*, QList<QPropertyAssignment> >::iterator it;
+ for (it = propertyAssignmentsForState.begin(); it != propertyAssignmentsForState.end(); ) {
+ QList<QPropertyAssignment>::iterator it2;
+ QAbstractState *s = it.key();
+ QList<QPropertyAssignment> &assignments = it.value();
+ for (it2 = assignments.begin(); it2 != assignments.end(); ) {
+ QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> > ret;
+ ret = initializeAnimation(anim, *it2);
+ QList<QAbstractAnimation*> handlers = ret.first;
+ if (!handlers.isEmpty()) {
+ for (int j = 0; j < handlers.size(); ++j) {
+ QAbstractAnimation *a = handlers.at(j);
+ propertyForAnimation.insert(a, *it2);
+ stateForAnimation.insert(a, s);
+ animationsForState[s].append(a);
+ // ### connect to just the top-level animation?
+ QObject::disconnect(a, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
+ QObject::connect(a, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
+ }
+ it2 = assignments.erase(it2);
+ } else {
+ ++it2;
+ }
+ for (int j = 0; j < ret.second.size(); ++j)
+ resetAnimationEndValues.insert(ret.second.at(j));
+ }
+ if (assignments.isEmpty())
+ it = propertyAssignmentsForState.erase(it);
+ else
+ ++it;
+ }
+ // We require that at least one animation is valid.
+ // ### generalize
+ QList<QVariantAnimation*> variantAnims = qFindChildren<QVariantAnimation*>(anim);
+ if (QVariantAnimation *va = qobject_cast<QVariantAnimation*>(anim))
+ variantAnims.append(va);
+
+ bool hasValidEndValue = false;
+ for (int j = 0; j < variantAnims.size(); ++j) {
+ if (variantAnims.at(j)->endValue().isValid()) {
+ hasValidEndValue = true;
+ break;
+ }
+ }
+
+ if (hasValidEndValue) {
+ anim->start();
+ }
+ }
+#endif // !QT_NO_ANIMATION
+
+ // Immediately set the properties that are not animated.
+ {
+ QHash<QAbstractState*, QList<QPropertyAssignment> >::const_iterator it;
+ for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) {
+ const QList<QPropertyAssignment> &assignments = it.value();
+ for (int i = 0; i < assignments.size(); ++i) {
+ const QPropertyAssignment &assn = assignments.at(i);
+ assn.object->setProperty(assn.propertyName, assn.value);
+ }
+ }
+ }
+
+ // Emit polished signal for entered states that have no animated properties.
+ for (int i = 0; i < enteredStates.size(); ++i) {
+ QState *s = qobject_cast<QState*>(enteredStates.at(i));
+ if (s && !animationsForState.contains(s))
+ QStatePrivate::get(s)->emitPolished();
+ }
+}
+
+bool QStateMachinePrivate::isFinal(const QAbstractState *s)
+{
+ return qobject_cast<const QFinalState*>(s) != 0;
+}
+
+bool QStateMachinePrivate::isParallel(const QAbstractState *s)
+{
+ const QState *ss = qobject_cast<const QState*>(s);
+ return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates);
+}
+
+bool QStateMachinePrivate::isCompound(const QAbstractState *s)
+{
+ const QState *group = qobject_cast<const QState*>(s);
+ if (!group)
+ return false;
+ return (!isParallel(group) && !QStatePrivate::get(group)->childStates().isEmpty())
+ || (qobject_cast<QStateMachine*>(group->parent()) != 0);
+}
+
+bool QStateMachinePrivate::isAtomic(const QAbstractState *s)
+{
+ const QState *ss = qobject_cast<const QState*>(s);
+ return (ss && QStatePrivate::get(ss)->childStates().isEmpty())
+ || isFinal(s);
+}
+
+
+bool QStateMachinePrivate::isDescendantOf(const QAbstractState *state, const QAbstractState *other)
+{
+ Q_ASSERT(state != 0);
+ for (QAbstractState *s = state->parentState(); s != 0; s = s->parentState()) {
+ if (s == other)
+ return true;
+ }
+ return false;
+}
+
+QList<QState*> QStateMachinePrivate::properAncestors(const QAbstractState *state, const QState *upperBound)
+{
+ Q_ASSERT(state != 0);
+ QList<QState*> result;
+ for (QState *s = state->parentState(); s && s != upperBound; s = s->parentState()) {
+ result.append(s);
+ }
+ return result;
+}
+
+bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const
+{
+ if (isCompound(s)) {
+ QState *grp = qobject_cast<QState*>(s);
+ QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
+ for (int i = 0; i < lst.size(); ++i) {
+ QAbstractState *cs = lst.at(i);
+ if (isFinal(cs) && configuration.contains(cs))
+ return true;
+ }
+ return false;
+ } else if (isParallel(s)) {
+ QState *grp = qobject_cast<QState*>(s);
+ QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
+ for (int i = 0; i < lst.size(); ++i) {
+ QAbstractState *cs = lst.at(i);
+ if (!isInFinalState(cs))
+ return false;
+ }
+ return true;
+ }
+ else
+ return false;
+}
+
+void QStateMachinePrivate::registerRestorable(QObject *object, const QByteArray &propertyName)
+{
+ RestorableId id(object, propertyName);
+ if (!registeredRestorables.contains(id))
+ registeredRestorables.insert(id, object->property(propertyName));
+}
+
+QList<QPropertyAssignment> QStateMachinePrivate::restorablesToPropertyList(const QHash<RestorableId, QVariant> &restorables) const
+{
+ QList<QPropertyAssignment> result;
+ QHash<RestorableId, QVariant>::const_iterator it;
+ for (it = restorables.constBegin(); it != restorables.constEnd(); ++it) {
+// qDebug() << "restorable:" << it.key().first << it.key().second << it.value();
+ result.append(QPropertyAssignment(it.key().first, it.key().second, it.value(), /*explicitlySet=*/false));
+ }
+ return result;
+}
+
+/*!
+ \internal
+ Returns true if the variable with the given \a id has been registered for restoration.
+*/
+bool QStateMachinePrivate::hasRestorable(QObject *object, const QByteArray &propertyName) const
+{
+ return registeredRestorables.contains(RestorableId(object, propertyName));
+}
+
+QVariant QStateMachinePrivate::restorableValue(QObject *object, const QByteArray &propertyName) const
+{
+ return registeredRestorables.value(RestorableId(object, propertyName), QVariant());
+}
+
+
+/*!
+ \internal
+ Unregisters the variable identified by \a id
+*/
+void QStateMachinePrivate::unregisterRestorable(QObject *object, const QByteArray &propertyName)
+{
+// qDebug() << "unregisterRestorable(" << object << propertyName << ")";
+ RestorableId id(object, propertyName);
+ registeredRestorables.remove(id);
+}
+
+QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context)
+{
+ // If the user sets the root state's error state to 0, we return the initial error state
+ if (context == 0)
+ return initialErrorStateForRoot;
+
+ // Find error state recursively in parent hierarchy if not set explicitly for context state
+ QAbstractState *errorState = 0;
+
+ QState *s = qobject_cast<QState*>(context);
+ if (s)
+ errorState = s->errorState();
+
+ if (!errorState)
+ errorState = findErrorState(context->parentState());
+
+ return errorState;
+}
+
+void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractState *currentContext)
+{
+ error = errorCode;
+
+ switch (errorCode) {
+ case QStateMachine::NoInitialStateError:
+ Q_ASSERT(currentContext != 0);
+
+ errorString = QStateMachine::tr("Missing initial state in compound state '%1'")
+ .arg(currentContext->objectName());
+
+ break;
+ case QStateMachine::NoDefaultStateInHistoryStateError:
+ Q_ASSERT(currentContext != 0);
+
+ errorString = QStateMachine::tr("Missing default state in history state '%1'")
+ .arg(currentContext->objectName());
+ break;
+
+ case QStateMachine::NoCommonAncestorForTransitionError:
+ Q_ASSERT(currentContext != 0);
+
+ errorString = QStateMachine::tr("No common ancestor for targets and source of transition from state '%1'")
+ .arg(currentContext->objectName());
+ break;
+ default:
+ errorString = QStateMachine::tr("Unknown error");
+ };
+
+ pendingErrorStates.clear();
+ pendingErrorStatesForDefaultEntry.clear();
+
+ QAbstractState *currentErrorState = findErrorState(currentContext);
+
+ // Avoid infinite loop if the error state itself has an error
+ if (currentContext == currentErrorState) {
+ Q_ASSERT(currentContext != initialErrorStateForRoot); // RootErrorState is broken
+ currentErrorState = initialErrorStateForRoot;
+ }
+
+ Q_ASSERT(currentErrorState != 0);
+ QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext);
+ addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry);
+}
+
+#ifndef QT_NO_ANIMATION
+
+QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> >
+QStateMachinePrivate::initializeAnimation(QAbstractAnimation *abstractAnimation,
+ const QPropertyAssignment &prop)
+{
+ QList<QAbstractAnimation*> handledAnimations;
+ QList<QAbstractAnimation*> localResetEndValues;
+ QAnimationGroup *group = qobject_cast<QAnimationGroup*>(abstractAnimation);
+ if (group) {
+ for (int i = 0; i < group->animationCount(); ++i) {
+ QAbstractAnimation *animationChild = group->animationAt(i);
+ QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> > ret;
+ ret = initializeAnimation(animationChild, prop);
+ handledAnimations << ret.first;
+ localResetEndValues << ret.second;
+ }
+ } else {
+ QPropertyAnimation *animation = qobject_cast<QPropertyAnimation *>(abstractAnimation);
+ if (animation != 0
+ && prop.object == animation->targetObject()
+ && prop.propertyName == animation->propertyName()) {
+
+ // Only change end value if it is undefined
+ if (!animation->endValue().isValid()) {
+ animation->setEndValue(prop.value);
+ localResetEndValues.append(animation);
+ }
+ handledAnimations.append(animation);
+ }
+ }
+ return qMakePair(handledAnimations, localResetEndValues);
+}
+
+void QStateMachinePrivate::_q_animationFinished()
+{
+ Q_Q(QStateMachine);
+ QAbstractAnimation *anim = qobject_cast<QAbstractAnimation*>(q->sender());
+ Q_ASSERT(anim != 0);
+ QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
+ if (resetAnimationEndValues.contains(anim)) {
+ qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize
+ resetAnimationEndValues.remove(anim);
+ }
+
+ // Set the final property value.
+ QPropertyAssignment assn = propertyForAnimation.take(anim);
+ Q_ASSERT(assn.object != 0);
+ assn.object->setProperty(assn.propertyName, assn.value);
+ if (!assn.explicitlySet)
+ unregisterRestorable(assn.object, assn.propertyName);
+
+ QAbstractState *state = stateForAnimation.take(anim);
+ Q_ASSERT(state != 0);
+ QHash<QAbstractState*, QList<QAbstractAnimation*> >::iterator it;
+ it = animationsForState.find(state);
+ Q_ASSERT(it != animationsForState.end());
+ QList<QAbstractAnimation*> &animations = it.value();
+ animations.removeOne(anim);
+ if (animations.isEmpty()) {
+ animationsForState.erase(it);
+ QStatePrivate::get(qobject_cast<QState*>(state))->emitPolished();
+ }
+}
+
+#endif // !QT_NO_ANIMATION
+
+namespace {
+
+class StartState : public QState
+{
+public:
+ StartState(QState *parent)
+ : QState(parent) {}
+protected:
+ void onEntry(QEvent *) {}
+ void onExit(QEvent *) {}
+};
+
+class InitialTransition : public QAbstractTransition
+{
+public:
+ InitialTransition(QAbstractState *target)
+ : QAbstractTransition(QList<QAbstractState*>() << target) {}
+protected:
+ virtual bool eventTest(QEvent *) const { return true; }
+ virtual void onTransition(QEvent *) {}
+};
+
+} // namespace
+
+void QStateMachinePrivate::_q_start()
+{
+ Q_Q(QStateMachine);
+ Q_ASSERT(state == Starting);
+ if (!rootState) {
+ state = NotRunning;
+ return;
+ }
+ QAbstractState *initial = rootState->initialState();
+ if (initial == 0)
+ setError(QStateMachine::NoInitialStateError, rootState);
+
+ configuration.clear();
+ qDeleteAll(internalEventQueue);
+ internalEventQueue.clear();
+ qDeleteAll(externalEventQueue);
+ externalEventQueue.clear();
+
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": starting";
+#endif
+ state = Running;
+ processingScheduled = true; // we call _q_process() below
+ emit q->started();
+
+ StartState *start = new StartState(rootState);
+ QAbstractTransition *initialTransition = new InitialTransition(initial);
+ start->addTransition(initialTransition);
+ QList<QAbstractTransition*> transitions;
+ transitions.append(initialTransition);
+ QEvent nullEvent(QEvent::None);
+ executeTransitionContent(&nullEvent, transitions);
+ enterStates(&nullEvent, transitions);
+ applyProperties(transitions, QList<QAbstractState*>() << start,
+ QList<QAbstractState*>() << initial);
+ delete start;
+
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": initial configuration:" << configuration;
+#endif
+ _q_process();
+}
+
+void QStateMachinePrivate::_q_process()
+{
+ Q_Q(QStateMachine);
+ Q_ASSERT(state == Running);
+ Q_ASSERT(!processing);
+ processing = true;
+ processingScheduled = false;
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": starting the event processing loop";
+#endif
+ while (processing) {
+ if (stop) {
+ stop = false;
+ processing = false;
+ stopProcessingReason = Stopped;
+ break;
+ }
+ QSet<QAbstractTransition*> enabledTransitions;
+ QEvent *e = new QEvent(QEvent::None);
+ enabledTransitions = selectTransitions(e);
+ if (enabledTransitions.isEmpty()) {
+ delete e;
+ e = 0;
+ }
+ if (enabledTransitions.isEmpty() && !internalEventQueue.isEmpty()) {
+ e = internalEventQueue.takeFirst();
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": dequeued internal event" << e << "of type" << e->type();
+#endif
+ enabledTransitions = selectTransitions(e);
+ if (enabledTransitions.isEmpty()) {
+ delete e;
+ e = 0;
+ }
+ }
+ if (enabledTransitions.isEmpty()) {
+ if (externalEventQueue.isEmpty()) {
+ if (internalEventQueue.isEmpty()) {
+ processing = false;
+ stopProcessingReason = EventQueueEmpty;
+ }
+ } else {
+ e = externalEventQueue.takeFirst();
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": dequeued external event" << e << "of type" << e->type();
+#endif
+ enabledTransitions = selectTransitions(e);
+ if (enabledTransitions.isEmpty()) {
+ delete e;
+ e = 0;
+ }
+ }
+ }
+ if (!enabledTransitions.isEmpty()) {
+ q->beginMicrostep(e);
+ microstep(e, enabledTransitions.toList());
+ q->endMicrostep(e);
+ }
+#ifdef QSTATEMACHINE_DEBUG
+ else {
+ qDebug() << q << ": no transitions enabled";
+ }
+#endif
+ delete e;
+ }
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": finished the event processing loop";
+#endif
+ switch (stopProcessingReason) {
+ case EventQueueEmpty:
+ break;
+ case Finished:
+ state = NotRunning;
+ emit q->finished();
+ break;
+ case Stopped:
+ state = NotRunning;
+ emit q->stopped();
+ break;
+ }
+}
+
+void QStateMachinePrivate::scheduleProcess()
+{
+ if ((state != Running) || processing || processingScheduled)
+ return;
+ processingScheduled = true;
+ QMetaObject::invokeMethod(q_func(), "_q_process", Qt::QueuedConnection);
+}
+
+void QStateMachinePrivate::registerTransitions(QAbstractState *state)
+{
+ QState *group = qobject_cast<QState*>(state);
+ if (!group)
+ return;
+ QList<QAbstractTransition*> transitions = QStatePrivate::get(group)->transitions();
+ for (int i = 0; i < transitions.size(); ++i) {
+ QAbstractTransition *t = transitions.at(i);
+ if (QSignalTransition *st = qobject_cast<QSignalTransition*>(t)) {
+ registerSignalTransition(st);
+ }
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ else if (QEventTransition *oet = qobject_cast<QEventTransition*>(t)) {
+ registerEventTransition(oet);
+ }
+#endif
+ }
+}
+
+void QStateMachinePrivate::unregisterTransition(QAbstractTransition *transition)
+{
+ if (QSignalTransition *st = qobject_cast<QSignalTransition*>(transition)) {
+ unregisterSignalTransition(st);
+ }
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ else if (QEventTransition *oet = qobject_cast<QEventTransition*>(transition)) {
+ unregisterEventTransition(oet);
+ }
+#endif
+}
+
+#ifndef QT_STATEMACHINE_SOLUTION
+
+static int senderSignalIndex(const QObject *sender)
+{
+ QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject*>(sender));
+ QMutexLocker(&d->threadData->mutex);
+ if (!d->currentSender)
+ return -1;
+
+ // Return -1 if d->currentSender isn't in d->senders
+ bool found = false;
+ for (int i = 0; !found && i < d->senders.count(); ++i)
+ found = (d->senders.at(i).sender == d->currentSender->sender);
+ if (!found)
+ return -1;
+ return d->currentSender->signal;
+}
+
+#endif
+
+void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transition)
+{
+ Q_Q(QStateMachine);
+ if (QSignalTransitionPrivate::get(transition)->signalIndex != -1)
+ return; // already registered
+ QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
+ if (!sender)
+ return;
+ QByteArray signal = QSignalTransitionPrivate::get(transition)->signal;
+ if (signal.startsWith('0'+QSIGNAL_CODE))
+ signal.remove(0, 1);
+ int signalIndex = sender->metaObject()->indexOfSignal(signal);
+ if (signalIndex == -1) {
+ qWarning("QSignalTransition: no such signal: %s::%s",
+ sender->metaObject()->className(), signal.constData());
+ return;
+ }
+ QList<int> &connectedSignalIndexes = connections[sender];
+ if (!connectedSignalIndexes.contains(signalIndex)) {
+#ifndef QT_STATEMACHINE_SOLUTION
+ if (!signalEventGenerator)
+ signalEventGenerator = new QSignalEventGenerator(q);
+#else
+ QSignalEventGenerator *signalEventGenerator = new QSignalEventGenerator(signalIndex, q);
+#endif
+ bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator,
+ signalEventGenerator->metaObject()->methodOffset());
+ if (!ok) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": FAILED to add signal transition from" << transition->sourceState()
+ << ": ( sender =" << sender << ", signal =" << (signal.mid(1))
+ << ", targets =" << transition->targetStates() << ")";
+#endif
+ return;
+ }
+ connectedSignalIndexes.append(signalIndex);
+ }
+ QSignalTransitionPrivate::get(transition)->signalIndex = signalIndex;
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": added signal transition from" << transition->sourceState()
+ << ": ( sender =" << sender << ", signal =" << (signal.mid(1))
+ << ", targets =" << transition->targetStates() << ")";
+#endif
+}
+
+void QStateMachinePrivate::unregisterSignalTransition(QSignalTransition *transition)
+{
+ int signalIndex = QSignalTransitionPrivate::get(transition)->signalIndex;
+ if (signalIndex == -1)
+ return; // not registered
+#ifndef QT_STATEMACHINE_SOLUTION
+ const QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
+ QList<int> &connectedSignalIndexes = connections[sender];
+ Q_ASSERT(connectedSignalIndexes.contains(signalIndex));
+ Q_ASSERT(signalEventGenerator != 0);
+ bool ok = QMetaObject::disconnect(sender, signalIndex, signalEventGenerator,
+ signalEventGenerator->metaObject()->methodOffset());
+ if (ok) {
+ connectedSignalIndexes.removeOne(signalIndex);
+ if (connectedSignalIndexes.isEmpty())
+ connections.remove(sender);
+ QSignalTransitionPrivate::get(transition)->signalIndex = -1;
+ }
+#endif
+}
+
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+void QStateMachinePrivate::registerEventTransition(QEventTransition *transition)
+{
+ Q_Q(QStateMachine);
+ if (QEventTransitionPrivate::get(transition)->registered)
+ return;
+ if (transition->eventType() >= QEvent::User) {
+ qWarning("QObject event transitions are not supported for custom types");
+ return;
+ }
+ QObject *object = QEventTransitionPrivate::get(transition)->object;
+ if (!object)
+ return;
+#ifndef QT_STATEMACHINE_SOLUTION
+ QObjectPrivate *od = QObjectPrivate::get(object);
+ if (!od->eventFilters.contains(q))
+#endif
+ object->installEventFilter(q);
+ qobjectEvents[object].insert(transition->eventType());
+ QEventTransitionPrivate::get(transition)->registered = true;
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": added event transition from" << transition->sourceState()
+ << ": ( object =" << object << ", event =" << transition->eventType()
+ << ", targets =" << transition->targetStates() << ")";
+#endif
+}
+
+void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transition)
+{
+ Q_Q(QStateMachine);
+ if (!QEventTransitionPrivate::get(transition)->registered)
+ return;
+ QObject *object = QEventTransitionPrivate::get(transition)->object;
+ QSet<QEvent::Type> &events = qobjectEvents[object];
+ events.remove(transition->eventType());
+ if (events.isEmpty()) {
+ qobjectEvents.remove(object);
+ object->removeEventFilter(q);
+ }
+ QEventTransitionPrivate::get(transition)->registered = false;
+}
+#endif
+
+void QStateMachinePrivate::handleTransitionSignal(const QObject *sender, int signalIndex,
+ void **argv)
+{
+ const QList<int> &connectedSignalIndexes = connections[sender];
+ Q_ASSERT(connectedSignalIndexes.contains(signalIndex));
+ const QMetaObject *meta = sender->metaObject();
+ QMetaMethod method = meta->method(signalIndex);
+ QList<QByteArray> parameterTypes = method.parameterTypes();
+ int argc = parameterTypes.count();
+ QList<QVariant> vargs;
+ for (int i = 0; i < argc; ++i) {
+ int type = QMetaType::type(parameterTypes.at(i));
+ vargs.append(QVariant(type, argv[i+1]));
+ }
+
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": sending signal event ( sender =" << sender
+ << ", signal =" << sender->metaObject()->method(signalIndex).signature() << ")";
+#endif
+ internalEventQueue.append(new QSignalEvent(sender, signalIndex, vargs));
+ scheduleProcess();
+}
+
+/*!
+ Constructs a new state machine with the given \a parent.
+*/
+QStateMachine::QStateMachine(QObject *parent)
+ : QObject(
+#ifndef QT_STATEMACHINE_SOLUTION
+ *new QStateMachinePrivate,
+#endif
+ parent)
+#ifdef QT_STATEMACHINE_SOLUTION
+ , d_ptr(new QStateMachinePrivate)
+#endif
+{
+#ifdef QT_STATEMACHINE_SOLUTION
+ d_ptr->q_ptr = this;
+#endif
+}
+
+/*!
+ \internal
+*/
+QStateMachine::QStateMachine(QStateMachinePrivate &dd, QObject *parent)
+ : QObject(
+#ifndef QT_STATEMACHINE_SOLUTION
+ dd,
+#endif
+ parent)
+#ifdef QT_STATEMACHINE_SOLUTION
+ , d_ptr(&dd)
+#endif
+{
+#ifdef QT_STATEMACHINE_SOLUTION
+ d_ptr->q_ptr = this;
+#endif
+}
+
+/*!
+ Destroys this state machine.
+*/
+QStateMachine::~QStateMachine()
+{
+#ifdef QT_STATEMACHINE_SOLUTION
+ delete d_ptr;
+#endif
+}
+
+namespace {
+
+class RootErrorState : public QAbstractState
+{
+public:
+ RootErrorState(QState *parent)
+ : QAbstractState(parent)
+ {
+ setObjectName(QString::fromLatin1("DefaultErrorState"));
+ }
+
+ void onEntry(QEvent *)
+ {
+ QAbstractStatePrivate *d = QAbstractStatePrivate::get(this);
+ QStateMachine *machine = d->machine();
+
+ qWarning("Unrecoverable error detected in running state machine: %s",
+ qPrintable(machine->errorString()));
+ }
+
+ void onExit(QEvent *) {}
+};
+
+class RootState : public QState
+{
+public:
+ RootState(QState *parent)
+ : QState(parent)
+ {
+ }
+
+ void onEntry(QEvent *) {}
+ void onExit(QEvent *) {}
+};
+
+} // namespace
+
+/*!
+ Returns this state machine's root state.
+*/
+QState *QStateMachine::rootState() const
+{
+ Q_D(const QStateMachine);
+ if (!d->rootState) {
+ const_cast<QStateMachinePrivate*>(d)->rootState = new RootState(0);
+ const_cast<QStateMachinePrivate*>(d)->initialErrorStateForRoot = new RootErrorState(d->rootState);
+ d->rootState->setParent(const_cast<QStateMachine*>(this));
+ d->rootState->setErrorState(d->initialErrorStateForRoot);
+ }
+ return d->rootState;
+}
+
+/*!
+ Returns the error state of the state machine's root state.
+
+ \sa QState::errorState()
+*/
+QAbstractState *QStateMachine::errorState() const
+{
+ return rootState()->errorState();
+}
+
+/*!
+ Sets the error state of this state machine's root state to be \a state. When a running state
+ machine encounters an error which puts it in an undefined state, it will enter an error state
+ based on the context of the error that occurred. It will enter this state regardless of what
+ is currently in the event queue.
+
+ If the erroneous state has an error state set, this will be entered by the machine. If no error
+ state has been set, the state machine will search the parent hierarchy recursively for an
+ error state. The error state of the root state can thus be seen as a global error state that
+ applies for the states for which a more specific error state has not been set.
+
+ Before entering the error state, the state machine will set the error code returned by error() and
+ error message returned by errorString().
+
+ The default error state will print a warning to the console containing the information returned by
+ errorString(). By setting a new error state on either the state machine itself, or on specific
+ states, you can fine tune error handling in the state machine.
+
+ If the root state's error state is set to 0, or if the error state selected by the machine itself
+ contains an error, the default error state will be used.
+
+ \sa QState::setErrorState(), rootState()
+*/
+void QStateMachine::setErrorState(QAbstractState *state)
+{
+ rootState()->setErrorState(state);
+}
+
+/*! \enum QStateMachine::Error
+
+ This enum type defines errors that can occur in the state machine at run time. When the state
+ machine encounters an unrecoverable error at run time, it will set the error code returned
+ by error(), the error message returned by errorString(), and enter an error state based on
+ the context of the error.
+
+ \value NoError No error has occurred.
+ \value NoInitialStateError The machine has entered a QState with children which does not have an
+ initial state set. The context of this error is the state which is missing an initial
+ state.
+ \value NoDefaultStateInHistoryStateError The machine has entered a QHistoryState which does not have
+ a default state set. The context of this error is the QHistoryState which is missing a
+ default state.
+ \value NoCommonAncestorForTransitionError The machine has selected a transition whose source
+ and targets are not part of the same tree of states, and thus are not part of the same
+ state machine. Commonly, this could mean that one of the states has not been given
+ any parent or added to any machine. The context of this error is the source state of
+ the transition.
+
+ \sa setErrorState()
+*/
+
+/*!
+ \enum QStateMachine::RestorePolicy
+
+ This enum specifies the restore policy type. The restore policy
+ takes effect when the machine enters a state which sets one or more
+ properties. If the restore policy is set to RestoreProperties,
+ the state machine will save the original value of the property before the
+ new value is set.
+
+ Later, when the machine either enters a state which does not set
+ a value for the given property, the property will automatically be restored
+ to its initial value.
+
+ Only one initial value will be saved for any given property. If a value for a property has
+ already been saved by the state machine, it will not be overwritten until the property has been
+ successfully restored.
+
+ \value DoNotRestoreProperties The state machine should not save the initial values of properties
+ and restore them later.
+ \value RestoreProperties The state machine should save the initial values of properties
+ and restore them later.
+
+ \sa QStateMachine::globalRestorePolicy QState::assignProperty()
+*/
+
+
+/*!
+ Returns the error code of the last error that occurred in the state machine.
+*/
+QStateMachine::Error QStateMachine::error() const
+{
+ Q_D(const QStateMachine);
+ return d->error;
+}
+
+/*!
+ Returns the error string of the last error that occurred in the state machine.
+*/
+QString QStateMachine::errorString() const
+{
+ Q_D(const QStateMachine);
+ return d->errorString;
+}
+
+/*!
+ Clears the error string and error code of the state machine.
+*/
+void QStateMachine::clearError()
+{
+ Q_D(QStateMachine);
+ d->errorString.clear();
+ d->error = NoError;
+}
+
+/*!
+ Returns the restore policy of the state machine.
+
+ \sa setGlobalRestorePolicy()
+*/
+QStateMachine::RestorePolicy QStateMachine::globalRestorePolicy() const
+{
+ Q_D(const QStateMachine);
+ return d->globalRestorePolicy;
+}
+
+/*!
+ Sets the restore policy of the state machine to \a restorePolicy. The default
+ restore policy is QAbstractState::DoNotRestoreProperties.
+
+ \sa globalRestorePolicy()
+*/
+void QStateMachine::setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy)
+{
+ Q_D(QStateMachine);
+ d->globalRestorePolicy = restorePolicy;
+}
+
+/*!
+ Returns this state machine's initial state, or 0 if no initial state has
+ been set.
+*/
+QAbstractState *QStateMachine::initialState() const
+{
+ Q_D(const QStateMachine);
+ if (!d->rootState)
+ return 0;
+ return d->rootState->initialState();
+}
+
+/*!
+ Sets this state machine's initial \a state.
+*/
+void QStateMachine::setInitialState(QAbstractState *state)
+{
+ Q_D(QStateMachine);
+ if (!d->rootState) {
+ if (!state)
+ return;
+ rootState()->setInitialState(state);
+ }
+ d->rootState->setInitialState(state);
+}
+
+/*!
+ Adds the given \a state to this state machine. The state becomes a top-level
+ state (i.e. a child of the rootState()).
+
+ If the state is already in a different machine, it will first be removed
+ from its old machine, and then added to this machine.
+
+ \sa removeState(), rootState(), setInitialState()
+*/
+void QStateMachine::addState(QAbstractState *state)
+{
+ if (!state) {
+ qWarning("QStateMachine::addState: cannot add null state");
+ return;
+ }
+ if (QAbstractStatePrivate::get(state)->machine() == this) {
+ qWarning("QStateMachine::addState: state has already been added to this machine");
+ return;
+ }
+ state->setParent(rootState());
+}
+
+/*!
+ Removes the given \a state from this state machine. The state machine
+ releases ownership of the state.
+
+ \sa addState()
+*/
+void QStateMachine::removeState(QAbstractState *state)
+{
+ if (!state) {
+ qWarning("QStateMachine::removeState: cannot remove null state");
+ return;
+ }
+ if (QAbstractStatePrivate::get(state)->machine() != this) {
+ qWarning("QStateMachine::removeState: state %p's machine (%p)"
+ " is different from this machine (%p)",
+ state, QAbstractStatePrivate::get(state)->machine(), this);
+ return;
+ }
+ state->setParent(0);
+}
+
+/*!
+ Returns whether this state machine is running.
+
+ start(), stop()
+*/
+bool QStateMachine::isRunning() const
+{
+ Q_D(const QStateMachine);
+ return (d->state == QStateMachinePrivate::Running);
+}
+
+/*!
+ Starts this state machine. The machine will reset its configuration and
+ transition to the initial state. When a final top-level state (QFinalState)
+ is entered, the machine will emit the finished() signal.
+
+ \sa started(), finished(), stop(), initialState()
+*/
+void QStateMachine::start()
+{
+ Q_D(QStateMachine);
+
+ if (rootState()->initialState() == 0) {
+ qWarning("QStateMachine::start: No initial state set for machine. Refusing to start.");
+ return;
+ }
+
+ switch (d->state) {
+ case QStateMachinePrivate::NotRunning:
+ d->state = QStateMachinePrivate::Starting;
+ QMetaObject::invokeMethod(this, "_q_start", Qt::QueuedConnection);
+ break;
+ case QStateMachinePrivate::Starting:
+ break;
+ case QStateMachinePrivate::Running:
+ qWarning("QStateMachine::start(): already running");
+ break;
+ }
+}
+
+/*!
+ Stops this state machine. The state machine will stop processing events and
+ then emit the stopped() signal.
+
+ \sa stopped(), start()
+*/
+void QStateMachine::stop()
+{
+ Q_D(QStateMachine);
+ switch (d->state) {
+ case QStateMachinePrivate::NotRunning:
+ break;
+ case QStateMachinePrivate::Starting:
+ // the machine will exit as soon as it enters the event processing loop
+ d->stop = true;
+ break;
+ case QStateMachinePrivate::Running:
+ d->stop = true;
+ d->scheduleProcess();
+ break;
+ }
+}
+
+/*!
+ Posts the given \a event for processing by this state machine, with a delay
+ of \a delay milliseconds.
+
+ This function returns immediately. The event is added to the state machine's
+ event queue. Events are processed in the order posted. The state machine
+ takes ownership of the event and deletes it once it has been processed.
+
+ You can only post events when the state machine is running.
+*/
+void QStateMachine::postEvent(QEvent *event, int delay)
+{
+ Q_D(QStateMachine);
+ if (d->state != QStateMachinePrivate::Running) {
+ qWarning("QStateMachine::postEvent: cannot post event when the state machine is not running");
+ return;
+ }
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << this << ": posting external event" << event << "with delay" << delay;
+#endif
+ if (delay) {
+ int tid = startTimer(delay);
+ d->delayedEvents[tid] = event;
+ } else {
+ d->externalEventQueue.append(event);
+ d->scheduleProcess();
+ }
+}
+
+/*!
+ \internal
+
+ Posts the given internal \a event for processing by this state machine.
+*/
+void QStateMachine::postInternalEvent(QEvent *event)
+{
+ Q_D(QStateMachine);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << this << ": posting internal event" << event;
+#endif
+ d->internalEventQueue.append(event);
+ d->scheduleProcess();
+}
+
+/*!
+ \internal
+
+ Returns the maximal consistent set of states (including parallel and final
+ states) that this state machine is currently in. If a state \c s is in the
+ configuration, it is always the case that the parent of \c s is also in
+ c. Note, however, that the rootState() is not an explicit member of the
+ configuration.
+*/
+QSet<QAbstractState*> QStateMachine::configuration() const
+{
+ Q_D(const QStateMachine);
+ return d->configuration;
+}
+
+/*!
+ \fn QStateMachine::started()
+
+ This signal is emitted when the state machine has entered its initial state
+ (QStateMachine::initialState).
+
+ \sa QStateMachine::finished(), QStateMachine::start()
+*/
+
+/*!
+ \fn QStateMachine::finished()
+
+ This signal is emitted when the state machine has reached a top-level final
+ state (QFinalState).
+
+ \sa QStateMachine::started()
+*/
+
+/*!
+ \fn QStateMachine::stopped()
+
+ This signal is emitted when the state machine has stopped.
+
+ \sa QStateMachine::stop(), QStateMachine::finished()
+*/
+
+/*!
+ \reimp
+*/
+bool QStateMachine::event(QEvent *e)
+{
+ Q_D(QStateMachine);
+ if (e->type() == QEvent::Timer) {
+ QTimerEvent *te = static_cast<QTimerEvent*>(e);
+ int tid = te->timerId();
+ if (d->delayedEvents.contains(tid)) {
+ killTimer(tid);
+ QEvent *ee = d->delayedEvents.take(tid);
+ d->externalEventQueue.append(ee);
+ d->scheduleProcess();
+ return true;
+ }
+ } else if (e->type() == QEvent::ChildAdded) {
+ QChildEvent *ce = static_cast<QChildEvent*>(e);
+ if (QAbstractState *state = qobject_cast<QAbstractState*>(ce->child())) {
+ if (state != rootState()) {
+ state->setParent(rootState());
+ return true;
+ }
+ }
+ }
+ return QObject::event(e);
+}
+
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+/*!
+ \reimp
+*/
+bool QStateMachine::eventFilter(QObject *watched, QEvent *event)
+{
+ Q_D(QStateMachine);
+ Q_ASSERT(d->qobjectEvents.contains(watched));
+ if (d->qobjectEvents[watched].contains(event->type()))
+ postEvent(new QWrappedEvent(watched, d->handler->cloneEvent(event)));
+ return false;
+}
+#endif
+
+/*!
+ \internal
+
+ This function is called when the state machine is about to select
+ transitions based on the given \a event.
+
+ The default implementation does nothing.
+*/
+void QStateMachine::beginSelectTransitions(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \internal
+
+ This function is called when the state machine has finished selecting
+ transitions based on the given \a event.
+
+ The default implementation does nothing.
+*/
+void QStateMachine::endSelectTransitions(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \internal
+
+ This function is called when the state machine is about to do a microstep.
+
+ The default implementation does nothing.
+*/
+void QStateMachine::beginMicrostep(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \internal
+
+ This function is called when the state machine has finished doing a
+ microstep.
+
+ The default implementation does nothing.
+*/
+void QStateMachine::endMicrostep(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+#ifndef QT_NO_ANIMATION
+
+/*!
+ Returns whether animations are enabled for this state machine.
+*/
+bool QStateMachine::animationsEnabled() const
+{
+ Q_D(const QStateMachine);
+ return d->animationsEnabled;
+}
+
+/*!
+ Sets whether animations are \a enabled for this state machine.
+*/
+void QStateMachine::setAnimationsEnabled(bool enabled)
+{
+ Q_D(QStateMachine);
+ d->animationsEnabled = enabled;
+}
+
+/*!
+ Adds a default \a animation to be considered for any transition.
+*/
+void QStateMachine::addDefaultAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QStateMachine);
+ d->defaultAnimations.append(animation);
+}
+
+/*!
+ Returns the list of default animations that will be considered for any transition.
+*/
+QList<QAbstractAnimation*> QStateMachine::defaultAnimations() const
+{
+ Q_D(const QStateMachine);
+ return d->defaultAnimations;
+}
+
+/*!
+ Removes \a animation from the list of default animations.
+*/
+void QStateMachine::removeDefaultAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QStateMachine);
+ d->defaultAnimations.removeAll(animation);
+}
+
+#endif // QT_NO_ANIMATION
+
+
+static const uint qt_meta_data_QSignalEventGenerator[] = {
+
+ // content:
+ 2, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 1, 12, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+ 0, 0, // constructors
+
+ // slots: signature, parameters, type, tag, flags
+ 23, 22, 22, 22, 0x0a,
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_QSignalEventGenerator[] = {
+ "QSignalEventGenerator\0\0execute()\0"
+};
+
+const QMetaObject QSignalEventGenerator::staticMetaObject = {
+ { &QObject::staticMetaObject, qt_meta_stringdata_QSignalEventGenerator,
+ qt_meta_data_QSignalEventGenerator, 0 }
+};
+
+const QMetaObject *QSignalEventGenerator::metaObject() const
+{
+ return &staticMetaObject;
+}
+
+void *QSignalEventGenerator::qt_metacast(const char *_clname)
+{
+ if (!_clname) return 0;
+ if (!strcmp(_clname, qt_meta_stringdata_QSignalEventGenerator))
+ return static_cast<void*>(const_cast< QSignalEventGenerator*>(this));
+ return QObject::qt_metacast(_clname);
+}
+
+int QSignalEventGenerator::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QObject::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ switch (_id) {
+ case 0: {
+#ifndef QT_STATEMACHINE_SOLUTION
+// ### in Qt 4.6 we can use QObject::senderSignalIndex()
+ int signalIndex = senderSignalIndex(this);
+ Q_ASSERT(signalIndex != -1);
+#endif
+ QStateMachine *machine = qobject_cast<QStateMachine*>(parent());
+ QStateMachinePrivate::get(machine)->handleTransitionSignal(sender(), signalIndex, _a);
+ break;
+ }
+ default: ;
+ }
+ _id -= 1;
+ }
+ return _id;
+}
+
+QSignalEventGenerator::QSignalEventGenerator(
+#ifdef QT_STATEMACHINE_SOLUTION
+ int sigIdx,
+#endif
+ QStateMachine *parent)
+ : QObject(parent)
+#ifdef QT_STATEMACHINE_SOLUTION
+ , signalIndex(sigIdx)
+#endif
+{
+}
+
+/*!
+ \class QSignalEvent
+
+ \brief The QSignalEvent class represents a Qt signal event.
+
+ \since 4.6
+ \ingroup statemachine
+
+ A signal event is generated by a QStateMachine in response to a Qt
+ signal. The QSignalTransition class provides a transition associated with a
+ signal event. QSignalEvent is part of \l{The State Machine Framework}.
+
+ The sender() function returns the object that generated the signal. The
+ signalIndex() function returns the index of the signal. The arguments()
+ function returns the arguments of the signal.
+
+ \sa QSignalTransition
+*/
+
+/*!
+ \internal
+
+ Constructs a new QSignalEvent object with the given \a sender, \a
+ signalIndex and \a arguments.
+*/
+QSignalEvent::QSignalEvent(const QObject *sender, int signalIndex,
+ const QList<QVariant> &arguments)
+ :
+#ifndef QT_STATEMACHINE_SOLUTION
+ QEvent(QEvent::Signal)
+#else
+ QEvent(QEvent::Type(QEvent::User-1))
+#endif
+ , m_sender(sender), m_signalIndex(signalIndex), m_arguments(arguments)
+{
+}
+
+/*!
+ Destroys this QSignalEvent.
+*/
+QSignalEvent::~QSignalEvent()
+{
+}
+
+/*!
+ \fn QSignalEvent::sender() const
+
+ Returns the object that emitted the signal.
+
+ \sa QObject::sender()
+*/
+
+/*!
+ \fn QSignalEvent::signalIndex() const
+
+ Returns the index of the signal.
+
+ \sa QMetaObject::indexOfSignal(), QMetaObject::method()
+*/
+
+/*!
+ \fn QSignalEvent::arguments() const
+
+ Returns the arguments of the signal.
+*/
+
+
+/*!
+ \class QWrappedEvent
+
+ \brief The QWrappedEvent class holds a clone of an event associated with a QObject.
+
+ \since 4.6
+ \ingroup statemachine
+
+ A wrapped event is generated by a QStateMachine in response to a Qt
+ event. The QEventTransition class provides a transition associated with a
+ such an event. QWrappedEvent is part of \l{The State Machine Framework}.
+
+ The object() function returns the object that generated the event. The
+ event() function returns a clone of the original event.
+
+ \sa QEventTransition
+*/
+
+/*!
+ \internal
+
+ Constructs a new QWrappedEvent object with the given \a object
+ and \a event.
+*/
+QWrappedEvent::QWrappedEvent(QObject *object, QEvent *event)
+#ifdef QT_STATEMACHINE_SOLUTION
+ : QEvent(QEvent::Type(QEvent::User-3))
+#else
+ : QEvent(QEvent::Wrapped)
+#endif
+ , m_object(object), m_event(event)
+{
+}
+
+/*!
+ Destroys this QWrappedEvent.
+*/
+QWrappedEvent::~QWrappedEvent()
+{
+}
+
+/*!
+ \fn QWrappedEvent::object() const
+
+ Returns the object that the event is associated with.
+*/
+
+/*!
+ \fn QWrappedEvent::event() const
+
+ Returns a clone of the original event.
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qstatemachine.cpp"
diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h
new file mode 100644
index 0000000..5dc6c0b
--- /dev/null
+++ b/src/corelib/statemachine/qstatemachine.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATEMACHINE_H
+#define QSTATEMACHINE_H
+
+#ifndef QT_STATEMACHINE_SOLUTION
+# include <QtCore/qabstractstate.h>
+#else
+# include "qabstractstate.h"
+#endif
+
+#include <QtCore/qlist.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qset.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEvent;
+class QAbstractState;
+class QState;
+
+class QStateMachinePrivate;
+class QAbstractAnimation;
+class QAbstractState;
+class Q_CORE_EXPORT QStateMachine : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QState* rootState READ rootState)
+ Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState)
+ Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState)
+ Q_PROPERTY(QString errorString READ errorString)
+ Q_PROPERTY(RestorePolicy globalRestorePolicy READ globalRestorePolicy WRITE setGlobalRestorePolicy)
+ Q_ENUMS(RestorePolicy)
+#ifndef QT_NO_ANIMATION
+ Q_PROPERTY(bool animationsEnabled READ animationsEnabled WRITE setAnimationsEnabled)
+#endif
+public:
+ enum RestorePolicy {
+ DoNotRestoreProperties,
+ RestoreProperties
+ };
+
+ enum Error {
+ NoError,
+ NoInitialStateError,
+ NoDefaultStateInHistoryStateError,
+ NoCommonAncestorForTransitionError
+ };
+
+ QStateMachine(QObject *parent = 0);
+ ~QStateMachine();
+
+ void addState(QAbstractState *state);
+ void removeState(QAbstractState *state);
+
+ QState *rootState() const;
+
+ QAbstractState *initialState() const;
+ void setInitialState(QAbstractState *state);
+
+ QAbstractState *errorState() const;
+ void setErrorState(QAbstractState *state);
+
+ Error error() const;
+ QString errorString() const;
+ void clearError();
+
+ bool isRunning() const;
+
+#ifndef QT_NO_ANIMATION
+ bool animationsEnabled() const;
+ void setAnimationsEnabled(bool enabled);
+
+ void addDefaultAnimation(QAbstractAnimation *animation);
+ QList<QAbstractAnimation *> defaultAnimations() const;
+ void removeDefaultAnimation(QAbstractAnimation *animation);
+#endif // QT_NO_ANIMATION
+
+ QStateMachine::RestorePolicy globalRestorePolicy() const;
+ void setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy);
+
+ void postEvent(QEvent *event, int delay = 0);
+
+ QSet<QAbstractState*> configuration() const;
+
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ bool eventFilter(QObject *watched, QEvent *event);
+#endif
+
+public Q_SLOTS:
+ void start();
+ void stop();
+
+Q_SIGNALS:
+ void started();
+ void stopped();
+ void finished();
+
+protected:
+ void postInternalEvent(QEvent *event);
+
+ virtual void beginSelectTransitions(QEvent *event);
+ virtual void endSelectTransitions(QEvent *event);
+
+ virtual void beginMicrostep(QEvent *event);
+ virtual void endMicrostep(QEvent *event);
+
+ bool event(QEvent *e);
+
+protected:
+#ifdef QT_STATEMACHINE_SOLUTION
+ QStateMachinePrivate *d_ptr;
+#endif
+ QStateMachine(QStateMachinePrivate &dd, QObject *parent);
+
+private:
+ Q_DISABLE_COPY(QStateMachine)
+ Q_DECLARE_PRIVATE(QStateMachine)
+ Q_PRIVATE_SLOT(d_func(), void _q_start())
+ Q_PRIVATE_SLOT(d_func(), void _q_process())
+#ifndef QT_NO_ANIMATION
+ Q_PRIVATE_SLOT(d_func(), void _q_animationFinished())
+#endif
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
new file mode 100644
index 0000000..bb4a78c
--- /dev/null
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATEMACHINE_P_H
+#define QSTATEMACHINE_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.
+//
+
+#ifndef QT_STATEMACHINE_SOLUTION
+#include <private/qobject_p.h>
+#endif
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qset.h>
+
+#include "qstate.h"
+#include "qstate_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEvent;
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+class QEventTransition;
+#endif
+class QSignalEventGenerator;
+class QSignalTransition;
+class QAbstractState;
+class QAbstractTransition;
+class QState;
+
+#ifndef QT_NO_ANIMATION
+class QAbstractAnimation;
+#endif
+
+class QStateMachine;
+class Q_CORE_EXPORT QStateMachinePrivate
+#ifndef QT_STATEMACHINE_SOLUTION
+ : public QObjectPrivate
+#endif
+{
+ Q_DECLARE_PUBLIC(QStateMachine)
+public:
+ enum State {
+ NotRunning,
+ Starting,
+ Running
+ };
+ enum StopProcessingReason {
+ EventQueueEmpty,
+ Finished,
+ Stopped
+ };
+
+ QStateMachinePrivate();
+ ~QStateMachinePrivate();
+
+ static QStateMachinePrivate *get(QStateMachine *q);
+
+ static QState *findLCA(const QList<QAbstractState*> &states);
+
+ static bool stateEntryLessThan(QAbstractState *s1, QAbstractState *s2);
+ static bool stateExitLessThan(QAbstractState *s1, QAbstractState *s2);
+
+ QAbstractState *findErrorState(QAbstractState *context);
+ void setError(QStateMachine::Error error, QAbstractState *currentContext);
+
+ // private slots
+ void _q_start();
+ void _q_process();
+#ifndef QT_NO_ANIMATION
+ void _q_animationFinished();
+#endif
+
+ void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList);
+ bool isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const;
+ QSet<QAbstractTransition*> selectTransitions(QEvent *event) const;
+ QList<QAbstractState*> exitStates(QEvent *event, const QList<QAbstractTransition*> &transitionList);
+ void executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &transitionList);
+ QList<QAbstractState*> enterStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions);
+ void addStatesToEnter(QAbstractState *s, QState *root,
+ QSet<QAbstractState*> &statesToEnter,
+ QSet<QAbstractState*> &statesForDefaultEntry);
+
+ void applyProperties(const QList<QAbstractTransition*> &transitionList,
+ const QList<QAbstractState*> &exitedStates,
+ const QList<QAbstractState*> &enteredStates);
+
+ bool isInFinalState(QAbstractState *s) const;
+ static bool isFinal(const QAbstractState *s);
+ static bool isParallel(const QAbstractState *s);
+ static bool isCompound(const QAbstractState *s);
+ static bool isAtomic(const QAbstractState *s);
+ static bool isDescendantOf(const QAbstractState *s, const QAbstractState *other);
+ static QList<QState*> properAncestors(const QAbstractState *s, const QState *upperBound);
+
+ void registerTransitions(QAbstractState *state);
+ void registerSignalTransition(QSignalTransition *transition);
+ void unregisterSignalTransition(QSignalTransition *transition);
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ void registerEventTransition(QEventTransition *transition);
+ void unregisterEventTransition(QEventTransition *transition);
+#endif
+ void unregisterTransition(QAbstractTransition *transition);
+ void handleTransitionSignal(const QObject *sender, int signalIndex,
+ void **args);
+ void scheduleProcess();
+
+ typedef QPair<QObject *, QByteArray> RestorableId;
+ QHash<RestorableId, QVariant> registeredRestorables;
+ void registerRestorable(QObject *object, const QByteArray &propertyName);
+ void unregisterRestorable(QObject *object, const QByteArray &propertyName);
+ bool hasRestorable(QObject *object, const QByteArray &propertyName) const;
+ QVariant restorableValue(QObject *object, const QByteArray &propertyName) const;
+ QList<QPropertyAssignment> restorablesToPropertyList(const QHash<RestorableId, QVariant> &restorables) const;
+
+ State state;
+ bool processing;
+ bool processingScheduled;
+ bool stop;
+ StopProcessingReason stopProcessingReason;
+ QState *rootState;
+ QSet<QAbstractState*> configuration;
+ QList<QEvent*> internalEventQueue;
+ QList<QEvent*> externalEventQueue;
+
+ QStateMachine::Error error;
+ QStateMachine::RestorePolicy globalRestorePolicy;
+
+ QString errorString;
+ QSet<QAbstractState *> pendingErrorStates;
+ QSet<QAbstractState *> pendingErrorStatesForDefaultEntry;
+ QAbstractState *initialErrorStateForRoot;
+
+#ifndef QT_NO_ANIMATION
+ bool animationsEnabled;
+
+ QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> >
+ initializeAnimation(QAbstractAnimation *abstractAnimation,
+ const QPropertyAssignment &prop);
+
+ QHash<QAbstractState*, QList<QAbstractAnimation*> > animationsForState;
+ QHash<QAbstractAnimation*, QPropertyAssignment> propertyForAnimation;
+ QHash<QAbstractAnimation*, QAbstractState*> stateForAnimation;
+ QSet<QAbstractAnimation*> resetAnimationEndValues;
+
+ QList<QAbstractAnimation *> defaultAnimations;
+ QMultiHash<QAbstractState *, QAbstractAnimation *> defaultAnimationsForSource;
+ QMultiHash<QAbstractState *, QAbstractAnimation *> defaultAnimationsForTarget;
+
+#endif // QT_NO_ANIMATION
+
+#ifndef QT_STATEMACHINE_SOLUTION
+ QSignalEventGenerator *signalEventGenerator;
+#endif
+ QHash<const QObject*, QList<int> > connections;
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ QHash<QObject*, QSet<QEvent::Type> > qobjectEvents;
+#endif
+ QHash<int, QEvent*> delayedEvents;
+
+ typedef QEvent* (*f_cloneEvent)(QEvent*);
+ struct Handler {
+ f_cloneEvent cloneEvent;
+ };
+
+ static const Handler *handler;
+
+#ifdef QT_STATEMACHINE_SOLUTION
+ QStateMachine *q_ptr;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qwrappedevent.h b/src/corelib/statemachine/qwrappedevent.h
new file mode 100644
index 0000000..b01c608
--- /dev/null
+++ b/src/corelib/statemachine/qwrappedevent.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWRAPPEDEVENT_H
+#define QWRAPPEDEVENT_H
+
+#include <QtCore/qcoreevent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QObject;
+
+class Q_CORE_EXPORT QWrappedEvent : public QEvent
+{
+public:
+ QWrappedEvent(QObject *object, QEvent *event);
+ ~QWrappedEvent();
+
+ inline QObject *object() const { return m_object; }
+ inline QEvent *event() const { return m_event; }
+
+private:
+ QObject *m_object;
+ QEvent *m_event;
+
+private:
+ Q_DISABLE_COPY(QWrappedEvent)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/statemachine.pri b/src/corelib/statemachine/statemachine.pri
new file mode 100644
index 0000000..5b19bc1
--- /dev/null
+++ b/src/corelib/statemachine/statemachine.pri
@@ -0,0 +1,30 @@
+HEADERS += $$PWD/qstatemachine.h \
+ $$PWD/qstatemachine_p.h \
+ $$PWD/qsignaleventgenerator_p.h \
+ $$PWD/qabstractstate.h \
+ $$PWD/qabstractstate_p.h \
+ $$PWD/qstate.h \
+ $$PWD/qstate_p.h \
+ $$PWD/qfinalstate.h \
+ $$PWD/qhistorystate.h \
+ $$PWD/qhistorystate_p.h \
+ $$PWD/qabstracttransition.h \
+ $$PWD/qabstracttransition_p.h \
+ $$PWD/qsignalevent.h \
+ $$PWD/qsignaltransition.h \
+ $$PWD/qsignaltransition_p.h
+
+SOURCES += $$PWD/qstatemachine.cpp \
+ $$PWD/qabstractstate.cpp \
+ $$PWD/qstate.cpp \
+ $$PWD/qfinalstate.cpp \
+ $$PWD/qhistorystate.cpp \
+ $$PWD/qabstracttransition.cpp \
+ $$PWD/qsignaltransition.cpp
+
+!contains(DEFINES, QT_NO_STATEMACHINE_EVENTFILTER) {
+HEADERS += $$PWD/qwrappedevent.h \
+ $$PWD/qeventtransition.h \
+ $$PWD/qeventtransition_p.h
+SOURCES += $$PWD/qeventtransition.cpp
+}
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
new file mode 100644
index 0000000..da86442
--- /dev/null
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -0,0 +1,844 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+
+| *property* | *Used for type* |
+| period | QEasingCurve::{In,Out,InOut,OutIn}Elastic |
+| amplitude | QEasingCurve::{In,Out,InOut,OutIn}Bounce, QEasingCurve::{In,Out,InOut,OutIn}Elastic |
+| overshoot | QEasingCurve::{In,Out,InOut,OutIn}Back |
+
+*/
+
+
+
+
+/*!
+ \class QEasingCurve
+ \ingroup group_animation
+ \brief The QEasingCurve class provides easing curves for controlling animation.
+
+ Easing curves describe a function that controls how the speed of the interpolation
+ between 0 and 1 should be. Easing curves allow transitions from
+ one value to another to appear more natural than a simple constant speed would allow.
+ The QEasingCurve class is usually used in conjunction with the QAnimation class,
+ but can be used on its own.
+
+ To calculate the speed of the interpolation, the easing curve provides the function
+ valueForProgress(), where the \a progress argument specifies the progress of the
+ interpolation: 0 is the start value of the interpolation, 1 is the end value of the
+ interpolation. The returned value is the effective progress of the interpolation.
+ If the returned value is the same as the input value for all input values the easing
+ curve is a linear curve. This is the default behaviour.
+
+ For example,
+ \code
+ QEasingCurve easing(QEasingCurve::InOutQuad);
+
+ for(qreal t = 0.0; t < 1.0; t+=0.1)
+ qWarning() << "Effective progress" << t << " is
+ << easing.valueForProgress(t);
+ \endcode
+ will print the effective progress of the interpolation between 0 and 1.
+
+ When using a QAnimation, the easing curve will be used to control the
+ progress of the interpolation between startValue and endValue:
+ \code
+ QAnimation animation;
+ animation.setStartValue(0);
+ animation.setEndValue(1000);
+ animation.setDuration(1000);
+ animation.setEasingCurve(QEasingCurve::InOutQuad);
+ \endcode
+ */
+
+/*!
+ \enum QEasingCurve::Type
+
+ The type of easing curve.
+
+ \value Linear \inlineimage qeasingcurve-linear.png
+ \br
+ Easing equation function for a simple linear tweening,
+ with no easing.
+ \value InQuad \inlineimage qeasingcurve-inquad.png
+ \br
+ Easing equation function for a quadratic (t^2) easing
+ in: accelerating from zero velocity.
+ \value OutQuad \inlineimage qeasingcurve-outquad.png
+ \br
+ Easing equation function for a quadratic (t^2) easing
+ out: decelerating to zero velocity.
+ \value InOutQuad \inlineimage qeasingcurve-inoutquad.png
+ \br
+ Easing equation function for a quadratic (t^2) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInQuad \inlineimage qeasingcurve-outinquad.png
+ \br
+ Easing equation function for a quadratic (t^2) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InCubic \inlineimage qeasingcurve-incubic.png
+ \br
+ Easing equation function for a cubic (t^3) easing
+ in: accelerating from zero velocity.
+ \value OutCubic \inlineimage qeasingcurve-outcubic.png
+ \br
+ Easing equation function for a cubic (t^3) easing
+ out: decelerating from zero velocity.
+ \value InOutCubic \inlineimage qeasingcurve-inoutcubic.png
+ \br
+ Easing equation function for a cubic (t^3) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInCubic \inlineimage qeasingcurve-outincubic.png
+ \br
+ Easing equation function for a cubic (t^3) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InQuart \inlineimage qeasingcurve-inquart.png
+ \br
+ Easing equation function for a quartic (t^4) easing
+ in: accelerating from zero velocity.
+ \value OutQuart \inlineimage qeasingcurve-outquart.png
+ \br
+ Easing equation function for a quartic (t^4) easing
+ out: decelerating from zero velocity.
+ \value InOutQuart \inlineimage qeasingcurve-inoutquart.png
+ \br
+ Easing equation function for a quartic (t^4) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInQuart \inlineimage qeasingcurve-outinquart.png
+ \br
+ Easing equation function for a quartic (t^4) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InQuint \inlineimage qeasingcurve-inquint.png
+ \br
+ Easing equation function for a quintic (t^5) easing
+ in: accelerating from zero velocity.
+ \value OutQuint \inlineimage qeasingcurve-outquint.png
+ \br
+ Easing equation function for a quintic (t^5) easing
+ out: decelerating from zero velocity.
+ \value InOutQuint \inlineimage qeasingcurve-inoutquint.png
+ \br
+ Easing equation function for a quintic (t^5) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInQuint \inlineimage qeasingcurve-outinquint.png
+ \br
+ Easing equation function for a quintic (t^5) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InSine \inlineimage qeasingcurve-insine.png
+ \br
+ Easing equation function for a sinusoidal (sin(t)) easing
+ in: accelerating from zero velocity.
+ \value OutSine \inlineimage qeasingcurve-outsine.png
+ \br
+ Easing equation function for a sinusoidal (sin(t)) easing
+ out: decelerating from zero velocity.
+ \value InOutSine \inlineimage qeasingcurve-inoutsine.png
+ \br
+ Easing equation function for a sinusoidal (sin(t)) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInSine \inlineimage qeasingcurve-outinsine.png
+ \br
+ Easing equation function for a sinusoidal (sin(t)) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InExpo \inlineimage qeasingcurve-inexpo.png
+ \br
+ Easing equation function for an exponential (2^t) easing
+ in: accelerating from zero velocity.
+ \value OutExpo \inlineimage qeasingcurve-outexpo.png
+ \br
+ Easing equation function for an exponential (2^t) easing
+ out: decelerating from zero velocity.
+ \value InOutExpo \inlineimage qeasingcurve-inoutexpo.png
+ \br
+ Easing equation function for an exponential (2^t) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInExpo \inlineimage qeasingcurve-outinexpo.png
+ \br
+ Easing equation function for an exponential (2^t) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InCirc \inlineimage qeasingcurve-incirc.png
+ \br
+ Easing equation function for a circular (sqrt(1-t^2)) easing
+ in: accelerating from zero velocity.
+ \value OutCirc \inlineimage qeasingcurve-outcirc.png
+ \br
+ Easing equation function for a circular (sqrt(1-t^2)) easing
+ out: decelerating from zero velocity.
+ \value InOutCirc \inlineimage qeasingcurve-inoutcirc.png
+ \br
+ Easing equation function for a circular (sqrt(1-t^2)) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInCirc \inlineimage qeasingcurve-outincirc.png
+ \br
+ Easing equation function for a circular (sqrt(1-t^2)) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InElastic \inlineimage qeasingcurve-inelastic.png
+ \br
+ Easing equation function for an elastic
+ (exponentially decaying sine wave) easing in:
+ accelerating from zero velocity. The peak amplitude
+ can be set with the \e amplitude parameter, and the
+ period of decay by the \e period parameter.
+ \value OutElastic \inlineimage qeasingcurve-outelastic.png
+ \br
+ Easing equation function for an elastic
+ (exponentially decaying sine wave) easing out:
+ decelerating from zero velocity. The peak amplitude
+ can be set with the \e amplitude parameter, and the
+ period of decay by the \e period parameter.
+ \value InOutElastic \inlineimage qeasingcurve-inoutelastic.png
+ \br
+ Easing equation function for an elastic
+ (exponentially decaying sine wave) easing in/out:
+ acceleration until halfway, then deceleration.
+ \value OutInElastic \inlineimage qeasingcurve-outinelastic.png
+ \br
+ Easing equation function for an elastic
+ (exponentially decaying sine wave) easing out/in:
+ deceleration until halfway, then acceleration.
+ \value InBack \inlineimage qeasingcurve-inback.png
+ \br
+ Easing equation function for a back (overshooting
+ cubic easing: (s+1)*t^3 - s*t^2) easing in:
+ accelerating from zero velocity.
+ \value OutBack \inlineimage qeasingcurve-outback.png
+ \br
+ Easing equation function for a back (overshooting
+ cubic easing: (s+1)*t^3 - s*t^2) easing out:
+ decelerating from zero velocity.
+ \value InOutBack \inlineimage qeasingcurve-inoutback.png
+ \br
+ Easing equation function for a back (overshooting
+ cubic easing: (s+1)*t^3 - s*t^2) easing in/out:
+ acceleration until halfway, then deceleration.
+ \value OutInBack \inlineimage qeasingcurve-outinback.png
+ \br
+ Easing equation function for a back (overshooting
+ cubic easing: (s+1)*t^3 - s*t^2) easing out/in:
+ deceleration until halfway, then acceleration.
+ \value InBounce \inlineimage qeasingcurve-inbounce.png
+ \br
+ Easing equation function for a bounce (exponentially
+ decaying parabolic bounce) easing in: accelerating
+ from zero velocity.
+ \value OutBounce \inlineimage qeasingcurve-outbounce.png
+ \br
+ Easing equation function for a bounce (exponentially
+ decaying parabolic bounce) easing out: decelerating
+ from zero velocity.
+ \value InOutBounce \inlineimage qeasingcurve-inoutbounce.png
+ \br
+ Easing equation function for a bounce (exponentially
+ decaying parabolic bounce) easing in/out:
+ acceleration until halfway, then deceleration.
+ \value OutInBounce \inlineimage qeasingcurve-outinbounce.png
+ \br
+ Easing equation function for a bounce (exponentially
+ decaying parabolic bounce) easing out/in:
+ deceleration until halfway, then acceleration.
+ \omitvalue InCurve
+ \omitvalue OutCurve
+ \omitvalue SineCurve
+ \omitvalue CosineCurve
+ \value Custom This is returned if the user have specified a custom curve type with setCustomType(). Note that you cannot call setType() with this value, but type() can return it.
+ \omitvalue NCurveTypes
+*/
+
+/*!
+ \typedef QEasingCurve::EasingFunction
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qeasingcurve.cpp 0
+
+*/
+
+#include "qeasingcurve.h"
+
+QT_BEGIN_NAMESPACE
+
+static bool isConfigFunction(QEasingCurve::Type type)
+{
+ return type >= QEasingCurve::InElastic
+ && type <= QEasingCurve::OutInBounce;
+}
+
+class QEasingCurveFunction
+{
+public:
+ enum Type { In, Out, InOut, OutIn };
+
+ QEasingCurveFunction(QEasingCurveFunction::Type type = In, qreal period = 0.3, qreal amplitude = 1.0,
+ qreal overshoot = 1.70158f)
+ : _t(type), _p(period), _a(amplitude), _o(overshoot)
+ { }
+ virtual ~QEasingCurveFunction() {}
+ virtual qreal value(qreal t);
+ virtual QEasingCurveFunction *copy() const;
+ bool operator==(const QEasingCurveFunction& other);
+
+ Type _t;
+ qreal _p;
+ qreal _a;
+ qreal _o;
+};
+
+qreal QEasingCurveFunction::value(qreal t)
+{
+ return t;
+}
+
+QEasingCurveFunction *QEasingCurveFunction::copy() const
+{
+ return new QEasingCurveFunction(_t, _p, _a, _o);
+}
+
+bool QEasingCurveFunction::operator==(const QEasingCurveFunction& other)
+{
+ return _t == other._t &&
+ _p == other._p &&
+ _a == other._a &&
+ _o == other._o;
+}
+
+#ifdef QT_EXPERIMENTAL_SOLUTION
+# include "easing.cpp"
+#else
+# include "../3rdparty/easing/easing.cpp"
+#endif
+
+class QEasingCurvePrivate
+{
+public:
+ QEasingCurvePrivate()
+ : type(QEasingCurve::Linear),
+ config(0),
+ func(&easeNone)
+ { }
+ void setType_helper(QEasingCurve::Type);
+
+ QEasingCurve::Type type;
+ QEasingCurveFunction *config;
+ QEasingCurve::EasingFunction func;
+};
+
+struct ElasticEase : public QEasingCurveFunction
+{
+ ElasticEase(Type type)
+ : QEasingCurveFunction(type, qreal(0.3), qreal(1.0))
+ { }
+
+ QEasingCurveFunction *copy() const
+ {
+ ElasticEase *rv = new ElasticEase(_t);
+ rv->_p = _p;
+ rv->_a = _a;
+ return rv;
+ }
+
+ qreal value(qreal t)
+ {
+ qreal p = (_p < 0) ? 0.3f : _p;
+ qreal a = (_a < 0) ? 1.0f : _a;
+ switch(_t) {
+ case In:
+ return easeInElastic(t, a, p);
+ case Out:
+ return easeOutElastic(t, a, p);
+ case InOut:
+ return easeInOutElastic(t, a, p);
+ case OutIn:
+ return easeOutInElastic(t, a, p);
+ default:
+ return t;
+ }
+ }
+};
+
+struct BounceEase : public QEasingCurveFunction
+{
+ BounceEase(Type type)
+ : QEasingCurveFunction(type, 0.3f, 1.0f)
+ { }
+
+ QEasingCurveFunction *copy() const
+ {
+ BounceEase *rv = new BounceEase(_t);
+ rv->_a = _a;
+ return rv;
+ }
+
+ qreal value(qreal t)
+ {
+ qreal a = (_a < 0) ? 1.0f : _a;
+ switch(_t) {
+ case In:
+ return easeInBounce(t, a);
+ case Out:
+ return easeOutBounce(t, a);
+ case InOut:
+ return easeInOutBounce(t, a);
+ case OutIn:
+ return easeOutInBounce(t, a);
+ default:
+ return t;
+ }
+ }
+};
+
+struct BackEase : public QEasingCurveFunction
+{
+ BackEase(Type type)
+ : QEasingCurveFunction(type, 0.3f, 1.0f, 1.70158f)
+ { }
+
+ QEasingCurveFunction *copy() const
+ {
+ BackEase *rv = new BackEase(_t);
+ rv->_o = _o;
+ return rv;
+ }
+
+ qreal value(qreal t)
+ {
+ qreal o = (_o < 0) ? 1.70158f : _o;
+ switch(_t) {
+ case In:
+ return easeInBack(t, o);
+ case Out:
+ return easeOutBack(t, o);
+ case InOut:
+ return easeInOutBack(t, o);
+ case OutIn:
+ return easeOutInBack(t, o);
+ default:
+ return t;
+ }
+ }
+};
+
+static QEasingCurve::EasingFunction curveToFunc(QEasingCurve::Type curve)
+{
+ switch(curve) {
+ case QEasingCurve::Linear:
+ return &easeNone;
+ case QEasingCurve::InQuad:
+ return &easeInQuad;
+ case QEasingCurve::OutQuad:
+ return &easeOutQuad;
+ case QEasingCurve::InOutQuad:
+ return &easeInOutQuad;
+ case QEasingCurve::OutInQuad:
+ return &easeOutInQuad;
+ case QEasingCurve::InCubic:
+ return &easeInCubic;
+ case QEasingCurve::OutCubic:
+ return &easeOutCubic;
+ case QEasingCurve::InOutCubic:
+ return &easeInOutCubic;
+ case QEasingCurve::OutInCubic:
+ return &easeOutInCubic;
+ case QEasingCurve::InQuart:
+ return &easeInQuart;
+ case QEasingCurve::OutQuart:
+ return &easeOutQuart;
+ case QEasingCurve::InOutQuart:
+ return &easeInOutQuart;
+ case QEasingCurve::OutInQuart:
+ return &easeOutInQuart;
+ case QEasingCurve::InQuint:
+ return &easeInQuint;
+ case QEasingCurve::OutQuint:
+ return &easeOutQuint;
+ case QEasingCurve::InOutQuint:
+ return &easeInOutQuint;
+ case QEasingCurve::OutInQuint:
+ return &easeOutInQuint;
+ case QEasingCurve::InSine:
+ return &easeInSine;
+ case QEasingCurve::OutSine:
+ return &easeOutSine;
+ case QEasingCurve::InOutSine:
+ return &easeInOutSine;
+ case QEasingCurve::OutInSine:
+ return &easeOutInSine;
+ case QEasingCurve::InExpo:
+ return &easeInExpo;
+ case QEasingCurve::OutExpo:
+ return &easeOutExpo;
+ case QEasingCurve::InOutExpo:
+ return &easeInOutExpo;
+ case QEasingCurve::OutInExpo:
+ return &easeOutInExpo;
+ case QEasingCurve::InCirc:
+ return &easeInCirc;
+ case QEasingCurve::OutCirc:
+ return &easeOutCirc;
+ case QEasingCurve::InOutCirc:
+ return &easeInOutCirc;
+ case QEasingCurve::OutInCirc:
+ return &easeOutInCirc;
+ // Internal for, compatibility with QTimeLine only ??
+ case QEasingCurve::InCurve:
+ return &easeInCurve;
+ case QEasingCurve::OutCurve:
+ return &easeOutCurve;
+ case QEasingCurve::SineCurve:
+ return &easeSineCurve;
+ case QEasingCurve::CosineCurve:
+ return &easeCosineCurve;
+ default:
+ return 0;
+ };
+}
+
+static QEasingCurveFunction *curveToFunctionObject(QEasingCurve::Type type)
+{
+ QEasingCurveFunction *curveFunc = 0;
+ switch(type) {
+ case QEasingCurve::InElastic:
+ curveFunc = new ElasticEase(ElasticEase::In);
+ break;
+ case QEasingCurve::OutElastic:
+ curveFunc = new ElasticEase(ElasticEase::Out);
+ break;
+ case QEasingCurve::InOutElastic:
+ curveFunc = new ElasticEase(ElasticEase::InOut);
+ break;
+ case QEasingCurve::OutInElastic:
+ curveFunc = new ElasticEase(ElasticEase::OutIn);
+ break;
+ case QEasingCurve::OutBounce:
+ curveFunc = new BounceEase(BounceEase::Out);
+ break;
+ case QEasingCurve::InBounce:
+ curveFunc = new BounceEase(BounceEase::In);
+ break;
+ case QEasingCurve::OutInBounce:
+ curveFunc = new BounceEase(BounceEase::OutIn);
+ break;
+ case QEasingCurve::InOutBounce:
+ curveFunc = new BounceEase(BounceEase::InOut);
+ break;
+ case QEasingCurve::InBack:
+ curveFunc = new BackEase(BackEase::In);
+ break;
+ case QEasingCurve::OutBack:
+ curveFunc = new BackEase(BackEase::Out);
+ break;
+ case QEasingCurve::InOutBack:
+ curveFunc = new BackEase(BackEase::InOut);
+ break;
+ case QEasingCurve::OutInBack:
+ curveFunc = new BackEase(BackEase::OutIn);
+ break;
+ default:
+ curveFunc = new QEasingCurveFunction(QEasingCurveFunction::In, 0.3f, 1.0f, 1.70158f); // ###
+ }
+
+ return curveFunc;
+}
+
+/*!
+ Constructs an easing curve of the given \a type.
+ */
+QEasingCurve::QEasingCurve(Type type)
+ : d_ptr(new QEasingCurvePrivate)
+{
+ setType(type);
+}
+
+/*!
+ Construct a copy of \a other.
+ */
+QEasingCurve::QEasingCurve(const QEasingCurve &other)
+: d_ptr(new QEasingCurvePrivate)
+{
+ // ### non-atomic, requires malloc on shallow copy
+ *d_ptr = *other.d_ptr;
+ if(other.d_ptr->config)
+ d_ptr->config = other.d_ptr->config->copy();
+}
+
+/*!
+ Destructor.
+ */
+
+QEasingCurve::~QEasingCurve()
+{
+ delete d_ptr;
+}
+
+/*!
+ Copy \a other.
+ */
+QEasingCurve &QEasingCurve::operator=(const QEasingCurve &other)
+{
+ // ### non-atomic, requires malloc on shallow copy
+ if (d_ptr->config) {
+ delete d_ptr->config;
+ d_ptr->config = 0;
+ }
+
+ *d_ptr = *other.d_ptr;
+ if(other.d_ptr->config)
+ d_ptr->config = other.d_ptr->config->copy();
+
+ return *this;
+}
+
+/*!
+ Compare this easing curve with \a other and returns true if they are
+ equal. It will also compare the properties of a curve.
+ */
+bool QEasingCurve::operator==(const QEasingCurve &other) const
+{
+ bool res = d_ptr->func == other.d_ptr->func
+ && d_ptr->type == other.d_ptr->type;
+ if (res && d_ptr->config && other.d_ptr->config) {
+ // catch the config content
+ res = d_ptr->config->operator==(*(other.d_ptr->config));
+ }
+ return res;
+}
+
+/*!
+ \fn bool QEasingCurve::operator!=(const QEasingCurve &other) const
+ Compare this easing curve with \a other and returns true if they are not equal.
+ It will also compare the properties of a curve.
+
+ \sa operator==()
+*/
+
+/*!
+ Returns the amplitude. This is not applicable for all curve types.
+ It is only applicable for bounce and elastic curves (curves of type()
+ QEasingCurve::InBounce, QEasingCurve::OutBounce, QEasingCurve::InOutBounce,
+ QEasingCurve::OutInBounce, QEasingCurve::InElastic, QEasingCurve::OutElastic,
+ QEasingCurve::InOutElastic or QEasingCurve::OutInElastic).
+ */
+qreal QEasingCurve::amplitude() const
+{
+ return d_ptr->config ? d_ptr->config->_a : 1.0;
+}
+
+/*!
+ Sets the amplitude to \a amplitude.
+
+ This will set the amplitude of the bounce or the amplitude of the
+ elastic "spring" effect. The higher the number, the higher the amplitude.
+ \sa amplitude()
+*/
+void QEasingCurve::setAmplitude(qreal amplitude)
+{
+ if (!d_ptr->config)
+ d_ptr->config = curveToFunctionObject(d_ptr->type);
+ d_ptr->config->_a = amplitude;
+}
+
+/*!
+ Returns the period. This is not applicable for all curve types.
+ It is only applicable if type() is QEasingCurve::InElastic, QEasingCurve::OutElastic,
+ QEasingCurve::InOutElastic or QEasingCurve::OutInElastic.
+ */
+qreal QEasingCurve::period() const
+{
+ return d_ptr->config ? d_ptr->config->_p : 0.3;
+}
+
+/*!
+ Sets the period to \a period.
+ Setting a small period value will give a high frequency of the curve. A
+ large period will give it a small frequency.
+
+ \sa period()
+*/
+void QEasingCurve::setPeriod(qreal period)
+{
+ if (!d_ptr->config)
+ d_ptr->config = curveToFunctionObject(d_ptr->type);
+ d_ptr->config->_p = period;
+}
+
+/*!
+ Returns the overshoot. This is not applicable for all curve types.
+ It is only applicable if type() is QEasingCurve::InBack, QEasingCurve::OutBack,
+ QEasingCurve::InOutBack or QEasingCurve::OutInBack.
+ */
+qreal QEasingCurve::overshoot() const
+{
+ return d_ptr->config ? d_ptr->config->_o : 1.70158f;
+}
+
+/*!
+ Sets the overshoot to \a overshoot.
+
+ 0 produces no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent.
+
+ \sa overshoot()
+*/
+void QEasingCurve::setOvershoot(qreal overshoot)
+{
+ if (!d_ptr->config)
+ d_ptr->config = curveToFunctionObject(d_ptr->type);
+ d_ptr->config->_o = overshoot;
+}
+
+/*!
+ Returns the type of the easing curve.
+*/
+QEasingCurve::Type QEasingCurve::type() const
+{
+ return d_ptr->type;
+}
+
+void QEasingCurvePrivate::setType_helper(QEasingCurve::Type newType)
+{
+ qreal amp = -1.0;
+ qreal period = -1.0;
+ qreal overshoot = -1.0;
+
+ if (config) {
+ amp = config->_a;
+ period = config->_p;
+ overshoot = config->_o;
+ delete config;
+ config = 0;
+ }
+
+ if (isConfigFunction(newType) || (amp != -1.0) || (period != -1.0) || (overshoot != -1.0)) {
+ config = curveToFunctionObject(newType);
+ if (amp != -1.0)
+ config->_a = amp;
+ if (period != -1.0)
+ config->_p = period;
+ if (overshoot != -1.0)
+ config->_o = overshoot;
+ func = 0;
+ } else if (newType != QEasingCurve::Custom) {
+ func = curveToFunc(newType);
+ }
+ Q_ASSERT((func == 0) == (config != 0));
+ type = newType;
+}
+
+/*!
+ Sets the type of the easing curve to \a type.
+*/
+void QEasingCurve::setType(Type type)
+{
+ if (d_ptr->type == type)
+ return;
+ if (type < Linear || type >= NCurveTypes - 1) {
+ qWarning("QEasingCurve: Invalid curve type %d", type);
+ return;
+ }
+
+ d_ptr->setType_helper(type);
+}
+
+/*!
+ Sets a custom easing curve that is defined by the user in the function \a func.
+ The signature of the function is qreal myEasingFunction(qreal progress),
+ where \e progress and the return value is considered to be normalized between 0 and 1.
+ (In some cases the return value can be outside that range)
+ After calling this function type() will return QEasingCurve::Custom.
+ \a func cannot be zero.
+
+ \sa customType()
+ \sa valueForProgress()
+*/
+void QEasingCurve::setCustomType(EasingFunction func)
+{
+ if (!func) {
+ qWarning("Function pointer must not be null");
+ return;
+ }
+ d_ptr->func = func;
+ d_ptr->setType_helper(Custom);
+}
+
+/*!
+ Returns the function pointer to the custom easing curve.
+ If type() does not return QEasingCurve::Custom, this function
+ will return 0.
+*/
+QEasingCurve::EasingFunction QEasingCurve::customType() const
+{
+ return d_ptr->type == Custom ? d_ptr->func : 0;
+}
+
+/*!
+ Return the effective progress for the easing curve at \a progress.
+ While \a progress must be between 0 and 1, the returned effective progress
+ can be outside those bounds. For instance, QEasingCurve::InBack will
+ return negative values in the beginning of the function.
+ */
+qreal QEasingCurve::valueForProgress(qreal progress) const
+{
+ progress = qBound<qreal>(0, progress, 1);
+ if (d_ptr->func)
+ return d_ptr->func(progress);
+ else if (d_ptr->config)
+ return d_ptr->config->value(progress);
+ else
+ return progress;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+#include <QtCore/qdebug.h>
+#include <QtCore/QString>
+QDebug operator<<(QDebug debug, const QEasingCurve &item)
+{
+ debug << "type:" << item.d_ptr->type
+ << "func:" << item.d_ptr->func;
+ if (item.d_ptr->config) {
+ debug << QString::fromAscii("period:%1").arg(item.d_ptr->config->_p, 0, 'f', 20)
+ << QString::fromAscii("amp:%1").arg(item.d_ptr->config->_a, 0, 'f', 20)
+ << QString::fromAscii("overshoot:%1").arg(item.d_ptr->config->_o, 0, 'f', 20);
+ }
+ return debug;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h
new file mode 100644
index 0000000..a240bc0
--- /dev/null
+++ b/src/corelib/tools/qeasingcurve.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEASINGCURVE_H
+#define QEASINGCURVE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qobjectdefs.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEasingCurvePrivate;
+class Q_CORE_EXPORT QEasingCurve
+{
+ Q_GADGET
+ Q_ENUMS(Type)
+public:
+ enum Type {
+ Linear,
+ InQuad, OutQuad, InOutQuad, OutInQuad,
+ InCubic, OutCubic, InOutCubic, OutInCubic,
+ InQuart, OutQuart, InOutQuart, OutInQuart,
+ InQuint, OutQuint, InOutQuint, OutInQuint,
+ InSine, OutSine, InOutSine, OutInSine,
+ InExpo, OutExpo, InOutExpo, OutInExpo,
+ InCirc, OutCirc, InOutCirc, OutInCirc,
+ InElastic, OutElastic, InOutElastic, OutInElastic,
+ InBack, OutBack, InOutBack, OutInBack,
+ InBounce, OutBounce, InOutBounce, OutInBounce,
+ InCurve, OutCurve, SineCurve, CosineCurve,
+ Custom, NCurveTypes
+ };
+
+ QEasingCurve(Type type = Linear);
+ QEasingCurve(const QEasingCurve &other);
+ ~QEasingCurve();
+
+ QEasingCurve &operator=(const QEasingCurve &other);
+ bool operator==(const QEasingCurve &other) const;
+ inline bool operator!=(const QEasingCurve &other) const
+ { return !(this->operator==(other)); }
+
+ qreal amplitude() const;
+ void setAmplitude(qreal amplitude);
+
+ qreal period() const;
+ void setPeriod(qreal period);
+
+ qreal overshoot() const;
+ void setOvershoot(qreal overshoot);
+
+ Type type() const;
+ void setType(Type type);
+ typedef qreal (*EasingFunction)(qreal progress);
+ void setCustomType(EasingFunction func);
+ EasingFunction customType() const;
+
+ qreal valueForProgress(qreal progress) const;
+private:
+ QEasingCurvePrivate *d_ptr;
+ friend Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QEasingCurve &item);
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QEasingCurve &item);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp
index 2979a09..78ce7bd 100644
--- a/src/corelib/tools/qtimeline.cpp
+++ b/src/corelib/tools/qtimeline.cpp
@@ -48,20 +48,6 @@
QT_BEGIN_NAMESPACE
-static const qreal pi = qreal(3.14159265359);
-static const qreal halfPi = pi / qreal(2.0);
-
-
-static inline qreal qt_sinProgress(qreal value)
-{
- return qSin((value * pi) - halfPi) / 2 + qreal(0.5);
-}
-
-static inline qreal qt_smoothBeginEndMixFactor(qreal value)
-{
- return qMin(qMax(1 - value * 2 + qreal(0.3), qreal(0.0)), qreal(1.0));
-}
-
class QTimeLinePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QTimeLine)
@@ -70,7 +56,7 @@ public:
: startTime(0), duration(1000), startFrame(0), endFrame(0),
updateInterval(1000 / 25),
totalLoopCount(1), currentLoopCount(0), currentTime(0), timerId(0),
- direction(QTimeLine::Forward), curveShape(QTimeLine::EaseInOutCurve),
+ direction(QTimeLine::Forward), easingCurve(QEasingCurve::InOutSine),
state(QTimeLine::NotRunning)
{ }
@@ -88,7 +74,7 @@ public:
QTime timer;
QTimeLine::Direction direction;
- QTimeLine::CurveShape curveShape;
+ QEasingCurve easingCurve;
QTimeLine::State state;
inline void setState(QTimeLine::State newState)
{
@@ -521,12 +507,68 @@ void QTimeLine::setUpdateInterval(int interval)
QTimeLine::CurveShape QTimeLine::curveShape() const
{
Q_D(const QTimeLine);
- return d->curveShape;
+ switch (d->easingCurve.type()) {
+ default:
+ case QEasingCurve::InOutSine:
+ return EaseInOutCurve;
+ case QEasingCurve::InCurve:
+ return EaseInCurve;
+ case QEasingCurve::OutCurve:
+ return EaseOutCurve;
+ case QEasingCurve::Linear:
+ return LinearCurve;
+ case QEasingCurve::SineCurve:
+ return SineCurve;
+ case QEasingCurve::CosineCurve:
+ return CosineCurve;
+ }
+ return EaseInOutCurve;
}
+
void QTimeLine::setCurveShape(CurveShape shape)
{
+ switch (shape) {
+ default:
+ case EaseInOutCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::InOutSine));
+ break;
+ case EaseInCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::InCurve));
+ break;
+ case EaseOutCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::OutCurve));
+ break;
+ case LinearCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::Linear));
+ break;
+ case SineCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::SineCurve));
+ break;
+ case CosineCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::CosineCurve));
+ break;
+ }
+}
+
+/*!
+ \property QTimeLine::easingCurve
+
+ Specifies the easing curve that the timeline will use.
+ If both easing curve and curveShape are set, the last set property will
+ override the previous one. (If valueForTime() is reimplemented it will
+ override both)
+*/
+
+QEasingCurve QTimeLine::easingCurve() const
+{
+ Q_D(const QTimeLine);
+ return d->easingCurve;
+}
+
+void QTimeLine::setEasingCurve(const QEasingCurve& curve)
+{
Q_D(QTimeLine);
- d->curveShape = shape;
+ d->easingCurve = curve;
}
/*!
@@ -606,42 +648,8 @@ qreal QTimeLine::valueForTime(int msec) const
Q_D(const QTimeLine);
msec = qMin(qMax(msec, 0), d->duration);
- // Simple linear interpolation
qreal value = msec / qreal(d->duration);
-
- switch (d->curveShape) {
- case EaseInOutCurve:
- value = qt_sinProgress(value);
- break;
- // SmoothBegin blends Smooth and Linear Interpolation.
- // Progress 0 - 0.3 : Smooth only
- // Progress 0.3 - ~ 0.5 : Mix of Smooth and Linear
- // Progress ~ 0.5 - 1 : Linear only
- case EaseInCurve: {
- const qreal sinProgress = qt_sinProgress(value);
- const qreal linearProgress = value;
- const qreal mix = qt_smoothBeginEndMixFactor(value);
- value = sinProgress * mix + linearProgress * (1 - mix);
- break;
- }
- case EaseOutCurve: {
- const qreal sinProgress = qt_sinProgress(value);
- const qreal linearProgress = value;
- const qreal mix = qt_smoothBeginEndMixFactor(1 - value);
- value = sinProgress * mix + linearProgress * (1 - mix);
- break;
- }
- case SineCurve:
- value = (qSin(((msec * pi * 2) / d->duration) - pi/2) + 1) / 2;
- break;
- case CosineCurve:
- value = (qCos(((msec * pi * 2) / d->duration) - pi/2) + 1) / 2;
- break;
- default:
- break;
- }
-
- return value;
+ return d->easingCurve.valueForProgress(value);
}
/*!
diff --git a/src/corelib/tools/qtimeline.h b/src/corelib/tools/qtimeline.h
index 18c3980..314dd7c 100644
--- a/src/corelib/tools/qtimeline.h
+++ b/src/corelib/tools/qtimeline.h
@@ -42,8 +42,11 @@
#ifndef QTIMELINE_H
#define QTIMELINE_H
+#include <QtCore/qeasingcurve.h>
#include <QtCore/qobject.h>
+QT_EXPERIMENTAL_USE_NAMESPACE
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -60,6 +63,7 @@ class Q_CORE_EXPORT QTimeLine : public QObject
Q_PROPERTY(Direction direction READ direction WRITE setDirection)
Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount)
Q_PROPERTY(CurveShape curveShape READ curveShape WRITE setCurveShape)
+ Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve)
public:
enum State {
NotRunning,
@@ -105,6 +109,9 @@ public:
CurveShape curveShape() const;
void setCurveShape(CurveShape shape);
+ QEasingCurve easingCurve() const;
+ void setEasingCurve(const QEasingCurve &curve);
+
int currentTime() const;
int currentFrame() const;
qreal currentValue() const;
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index e5bf7e4..41557f0 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -11,6 +11,7 @@ HEADERS += \
tools/qcryptographichash.h \
tools/qdatetime.h \
tools/qdatetime_p.h \
+ tools/qeasingcurve.h \
tools/qhash.h \
tools/qline.h \
tools/qlinkedlist.h \
@@ -46,6 +47,7 @@ SOURCES += \
tools/qcryptographichash.cpp \
tools/qdatetime.cpp \
tools/qdumper.cpp \
+ tools/qeasingcurve.cpp \
tools/qhash.cpp \
tools/qline.cpp \
tools/qlinkedlist.cpp \
diff --git a/src/declarative/3rdparty/3rdparty.pri b/src/declarative/3rdparty/3rdparty.pri
new file mode 100644
index 0000000..fc78cb2
--- /dev/null
+++ b/src/declarative/3rdparty/3rdparty.pri
@@ -0,0 +1,5 @@
+HEADERS += \
+ 3rdparty/qlistmodelinterface.h\
+
+SOURCES += \
+ 3rdparty/qlistmodelinterface.cpp \
diff --git a/src/declarative/3rdparty/qlistmodelinterface.cpp b/src/declarative/3rdparty/qlistmodelinterface.cpp
new file mode 100644
index 0000000..75960a1
--- /dev/null
+++ b/src/declarative/3rdparty/qlistmodelinterface.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlistmodelinterface.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QListModelInterface
+ \brief The QListModelInterface class can be subclassed to provide C++ models to QFx Views
+
+ This class is comprised primarily of pure virtual functions which
+ you must implement in a subclass. You can then use the subclass
+ as a model for a QFx view, such as a QFxListView.
+*/
+
+/*! \fn QListModelInterface::QListModelInterface(QObject *parent)
+ Constructs a QListModelInterface with the specified \a parent.
+*/
+
+ /*! \fn QListModelInterface::QListModelInterface(QObjectPrivate &dd, QObject *parent)
+
+ \internal
+ */
+
+/*! \fn QListModelInterface::~QListModelInterface()
+ The destructor is virtual.
+ */
+
+/*! \fn int QListModelInterface::count() const
+ Returns the number of data entries in the model.
+*/
+
+/*! \fn QHash<int,QVariant> QListModelInterface::data(int index, const QList<int>& roles) const
+ Returns the data at the given \a index for the specifed \a roles.
+*/
+
+/*! \fn bool QListModelInterface::setData(int index, const QHash<int,QVariant>& values)
+ Sets the data at the given \a index. \a values is a mapping of
+ QVariant values to roles. Returns false.
+*/
+
+/*! \fn QList<int> QListModelInterface::roles() const
+ Returns the list of roles for which the list model interface
+ provides data.
+*/
+
+/*! \fn QString QListModelInterface::toString(int role) const
+ Returns a string description of the specified \a role.
+*/
+
+/*! \fn void QListModelInterface::itemsInserted(int index, int count)
+ Emit this signal when \a count items are inserted at \a index.
+ */
+
+/*! \fn void QListModelInterface::itemsRemoved(int index, int count)
+ Emit this signal when \a count items are removed at \a index.
+ */
+
+/*! \fn void QListModelInterface::itemsMoved(int from, int to, int count)
+ Emit this signal when \a count items are moved from index \a from
+ to index \a to.
+ */
+
+/*! \fn void QListModelInterface::itemsChanged(int index, int count, const QList<int> &roles)
+ Emit this signal when \a count items at \a index have had their
+ \a roles changed.
+ */
+
+QT_END_NAMESPACE
diff --git a/src/declarative/3rdparty/qlistmodelinterface.h b/src/declarative/3rdparty/qlistmodelinterface.h
new file mode 100644
index 0000000..19284ca
--- /dev/null
+++ b/src/declarative/3rdparty/qlistmodelinterface.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLISTMODELINTERFACE_H
+#define QLISTMODELINTERFACE_H
+
+#include <QHash>
+#include <QVariant>
+#include <qfxglobal.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QListModelInterface : public QObject
+{
+ Q_OBJECT
+ public:
+ QListModelInterface(QObject *parent = 0) : QObject(parent) {}
+ virtual ~QListModelInterface() {}
+
+ virtual int count() const = 0;
+ virtual QHash<int,QVariant> data(int index, const QList<int>& roles = QList<int>()) const = 0;
+ virtual bool setData(int index, const QHash<int,QVariant>& values)
+ { Q_UNUSED(index); Q_UNUSED(values); return false; }
+
+ virtual QList<int> roles() const = 0;
+ virtual QString toString(int role) const = 0;
+
+ Q_SIGNALS:
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void itemsChanged(int index, int count, const QList<int> &roles);
+
+ protected:
+ QListModelInterface(QObjectPrivate &dd, QObject *parent)
+ : QObject(dd, parent) {}
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif //QTREEMODELINTERFACE_H
diff --git a/src/declarative/canvas/canvas.pri b/src/declarative/canvas/canvas.pri
new file mode 100644
index 0000000..8abfd99
--- /dev/null
+++ b/src/declarative/canvas/canvas.pri
@@ -0,0 +1,19 @@
+SOURCES += \
+ canvas/qsimplecanvas.cpp \
+ canvas/qsimplecanvasitem.cpp \
+ canvas/qsimplecanvasfilter.cpp \
+ canvas/qsimplecanvasserver.cpp
+
+HEADERS += \
+ canvas/qsimplecanvas.h \
+ canvas/qsimplecanvasitem.h \
+ canvas/qsimplecanvasfilter.h \
+ canvas/qsimplecanvas_p.h \
+ canvas/qsimplecanvasitem_p.h \
+ canvas/qsimplecanvasfilter_p.h \
+ canvas/qsimplecanvasserver_p.h
+
+contains(QT_CONFIG, opengles2): SOURCES += canvas/qsimplecanvas_opengl.cpp
+else:contains(QT_CONFIG, opengles1): SOURCES += canvas/qsimplecanvas_opengl1.cpp
+else:SOURCES += canvas/qsimplecanvas_software.cpp
+SOURCES += canvas/qsimplecanvas_graphicsview.cpp
diff --git a/src/declarative/canvas/qsimplecanvas.cpp b/src/declarative/canvas/qsimplecanvas.cpp
new file mode 100644
index 0000000..e1dd0e8
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas.cpp
@@ -0,0 +1,1023 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwidget.h"
+#include "qmutex.h"
+#include "qdebug.h"
+#include "qcoreapplication.h"
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvas_p.h"
+#include "qtimer.h"
+#include "qdatetime.h"
+#include "qgraphicssceneevent.h"
+#if defined(QFX_RENDER_OPENGL)
+#include <glheaders.h>
+#endif
+#include "qboxlayout.h"
+#include "qsimplecanvasserver_p.h"
+#include "qsimplecanvas.h"
+
+
+QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(fullUpdate, GFX_CANVAS_FULL_UPDATE);
+DEFINE_BOOL_CONFIG_OPTION(continuousUpdate, GFX_CANVAS_CONTINUOUS_UPDATE);
+DEFINE_BOOL_CONFIG_OPTION(useSimpleCanvas, QFX_USE_SIMPLECANVAS);
+
+template<class T, int s = 60>
+class CircularList
+{
+public:
+ CircularList()
+ : _first(0), _size(0) {}
+
+ void append(const T &t)
+ {
+ int entry = (_first + _size) % s;
+ _array[entry] = t;
+ if (_size == s)
+ _first = (_first + 1) % s;
+ else
+ _size++;
+ }
+
+ int size() const
+ {
+ return _size;
+ }
+
+ T &operator[](int idx)
+ {
+ Q_ASSERT(idx < _size);
+ int entry = (_first + idx) % s;
+ return _array[entry];
+ }
+
+ void clear()
+ {
+ _first = 0;
+ _size = 0;
+ }
+private:
+ int _first;
+ int _size;
+ T _array[s];
+};
+
+
+class QSimpleCanvasRootLayer : public QSimpleCanvasLayer
+{
+public:
+ QSimpleCanvasRootLayer(QSimpleCanvas *);
+ virtual void addDirty(QSimpleCanvasItem *);
+ virtual void remDirty(QSimpleCanvasItem *);
+
+private:
+ friend class QSimpleCanvasItem;
+ QSimpleCanvas *_canvas;
+};
+
+void QSimpleCanvasRootLayer::addDirty(QSimpleCanvasItem *i)
+{
+ _canvas->addDirty(i);
+}
+
+void QSimpleCanvasRootLayer::remDirty(QSimpleCanvasItem *i)
+{
+ _canvas->remDirty(i);
+}
+
+void QSimpleCanvasPrivate::clearFocusPanel(QSimpleCanvasItem *panel)
+{
+ if (q->activeFocusPanel() == panel) {
+ focusPanels.pop();
+
+ switchToFocusPanel(q->activeFocusPanel(), panel, Qt::OtherFocusReason);
+ panel->activePanelOutEvent();
+ } else {
+ for (int ii = 0; ii < focusPanels.count(); ++ii)
+ if (focusPanels.at(ii) == panel) {
+ focusPanels.remove(ii);
+ break;
+ }
+ }
+}
+
+void QSimpleCanvasPrivate::switchToFocusPanel(QSimpleCanvasItem *panel, QSimpleCanvasItem *wasPanel, Qt::FocusReason focusReason)
+{
+ if (panel)
+ panel->activePanelInEvent();
+
+ QSimpleCanvasItem *wasFocusRoot = focusPanelData.value(wasPanel);
+ if (wasFocusRoot)
+ clearActiveFocusItem(wasFocusRoot, focusReason);
+
+ QSimpleCanvasItem *newFocusRoot = focusPanelData.value(panel);
+ if (newFocusRoot)
+ setFocusItem(newFocusRoot, focusReason);
+}
+
+void QSimpleCanvasPrivate::setActiveFocusPanel(QSimpleCanvasItem *panel, Qt::FocusReason focusReason)
+{
+ if (q->activeFocusPanel() == panel)
+ return;
+
+ if (panel) {
+ for (int ii = 0; ii < focusPanels.count(); ++ii)
+ if (focusPanels.at(ii) == panel) {
+ focusPanels.remove(ii);
+ break;
+ }
+ }
+ QSimpleCanvasItem *old = q->activeFocusPanel();
+ if (panel)
+ focusPanels << panel;
+ switchToFocusPanel(panel, old, focusReason);
+ if (old)
+ old->activePanelOutEvent();
+}
+
+void QSimpleCanvasPrivate::clearActiveFocusItem(QSimpleCanvasItem *item,
+ Qt::FocusReason focusReason)
+{
+ if (!item || !item->d_func())
+ return;
+
+ if (!item->d_func()->hasActiveFocus)
+ return;
+
+ item->d_func()->hasActiveFocus = false;
+ if (item->options() & QSimpleCanvasItem::IsFocusRealm) {
+ QSimpleCanvasItem *newItem = focusPanelData.value(item);
+ if (newItem) {
+ clearActiveFocusItem(newItem, focusReason);
+ } else {
+ focusItem = 0;
+ QFocusEvent event(QEvent::FocusOut, focusReason);
+ item->focusOutEvent(&event);
+ }
+ } else {
+ focusItem = 0;
+ QFocusEvent event(QEvent::FocusOut, focusReason);
+ item->focusOutEvent(&event);
+ }
+
+ if (item->options() & QSimpleCanvasItem::AcceptsInputMethods){
+ if (q->testAttribute(Qt::WA_InputMethodEnabled))
+ q->setAttribute(Qt::WA_InputMethodEnabled,false);
+ }
+ item->activeFocusChanged(true);
+}
+
+void QSimpleCanvasPrivate::setActiveFocusItem(QSimpleCanvasItem *item,
+ Qt::FocusReason focusReason)
+{
+ while(true) {
+ item->d_func()->setActiveFocus(true);
+ item->activeFocusChanged(true);
+ if (item->options() & QSimpleCanvasItem::IsFocusRealm) {
+ QSimpleCanvasItem *newItem = focusPanelData.value(item);
+ if (newItem)
+ item = newItem;
+ else
+ break;
+ } else {
+ break;
+ }
+ }
+
+ if (item->options() & QSimpleCanvasItem::AcceptsInputMethods){
+ if (!q->testAttribute(Qt::WA_InputMethodEnabled))
+ q->setAttribute(Qt::WA_InputMethodEnabled,true);
+ }
+ focusItem = item;
+ QFocusEvent event(QEvent::FocusIn, focusReason);
+ focusItem->focusInEvent(&event);
+}
+
+void QSimpleCanvasPrivate::clearFocusItem(QSimpleCanvasItem *item)
+{
+ // XXX
+#if 0
+ while(item->focusProxy())
+ item = item->focusProxy();
+#endif
+
+ QSimpleCanvasItem *scope = 0;
+ QSimpleCanvasItem *citem = item;
+ while(citem && !scope) {
+ if (citem->options() & QSimpleCanvasItem::IsFocusPanel)
+ scope = citem;
+ else if (citem != item && citem->options() & QSimpleCanvasItem::IsFocusRealm)
+ scope = citem;
+ citem = citem->parent();
+ }
+ Q_ASSERT(scope); // At the very least we'll find the canvas root
+
+ bool isActive = false;
+
+ if (scope->options() & QSimpleCanvasItem::IsFocusPanel)
+ isActive = (scope == q->activeFocusPanel());
+ else if (scope->options() & QSimpleCanvasItem::IsFocusRealm)
+ isActive = scope->hasActiveFocus();
+
+ if (isActive) clearActiveFocusItem(item, Qt::OtherFocusReason);
+ item->d_func()->setFocus(false);
+ item->focusChanged(false);
+
+ focusPanelData.insert(scope, 0);
+
+ if (lastFocusItem == item)
+ lastFocusItem = 0;
+ if (focusItem == item)
+ focusItem = 0;
+
+ if (scope->options() & QSimpleCanvasItem::IsFocusRealm && scope->hasActiveFocus()) {
+ setActiveFocusItem(scope, Qt::OtherFocusReason);
+ } else {
+ QSimpleCanvasItem *item = QSimpleCanvasItem::findNextFocus(scope);
+ if (item)
+ item->setFocus(true);
+ }
+}
+
+void QSimpleCanvasPrivate::setFocusItem(QSimpleCanvasItem *item,
+ Qt::FocusReason focusReason,
+ bool overwrite)
+{
+ Q_ASSERT(item);
+
+ // XXX
+#if 0
+ while(item->focusProxy())
+ item = item->focusProxy();
+#endif
+
+ if (item == focusItem)
+ return;
+
+ QSimpleCanvasItem *scope = 0;
+ QSimpleCanvasItem *citem = item;
+ while(citem && !scope) {
+ if (citem->options() & QSimpleCanvasItem::IsFocusPanel)
+ scope = citem;
+ else if (citem != item && citem->options() & QSimpleCanvasItem::IsFocusRealm)
+ scope = citem;
+ citem = citem->parent();
+ }
+ Q_ASSERT(scope); // At the very least we'll find the canvas root
+
+ if (!overwrite && focusPanelData.contains(scope)) {
+ item->d_func()->setFocus(false);
+ item->focusChanged(false);
+ return;
+ }
+
+ QSimpleCanvasItem *oldFocus = focusPanelData.value(scope);
+ bool isActive = false;
+
+ if (scope->options() & QSimpleCanvasItem::IsFocusPanel)
+ isActive = (scope == q->activeFocusPanel());
+ else if (scope->options() & QSimpleCanvasItem::IsFocusRealm)
+ isActive = scope->hasActiveFocus();
+
+ if (oldFocus) {
+ if (isActive) clearActiveFocusItem(oldFocus, focusReason);
+ oldFocus->d_func()->setFocus(false);
+ oldFocus->focusChanged(false);
+ }
+
+ focusPanelData.insert(scope, item);
+
+ if (isActive)
+ lastFocusItem = item;
+
+ if (item) {
+ item->d_func()->setFocus(true);
+ item->focusChanged(true);
+ if (isActive)
+ setActiveFocusItem(item, focusReason);
+ }
+}
+
+
+bool QSimpleCanvas::eventFilter(QObject *obj, QEvent *event)
+{
+ Q_UNUSED(obj);
+ switch (event->type()) {
+ case QEvent::GraphicsSceneMouseMove: {
+ QGraphicsSceneMouseEvent *me = (QGraphicsSceneMouseEvent*)event;
+ if (!me->buttons())
+ break;
+ }
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease: {
+ //same logic as filter() function
+ for (int ii = 0; ii < d->mouseFilters.count(); ++ii) {
+ if (d->mouseFilters.at(ii)->mouseFilter((QGraphicsSceneMouseEvent*)event))
+ return true;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return false;
+}
+
+void QSimpleCanvasPrivate::installMouseFilter(QSimpleCanvasItem *item)
+{
+ mouseFilters << item;
+}
+
+void QSimpleCanvasPrivate::removeMouseFilter(QSimpleCanvasItem *item)
+{
+ mouseFilters.removeAll(item);
+}
+
+bool QSimpleCanvasPrivate::filter(QMouseEvent *e)
+{
+ if (mouseFilters.isEmpty())
+ return false;
+
+ QGraphicsSceneMouseEvent *me = mouseEventToSceneMouseEvent(e, e->pos());
+ for (int ii = 0; ii < mouseFilters.count(); ++ii) {
+ if (mouseFilters.at(ii)->mouseFilter(me)) {
+ delete me;
+ return true;
+ }
+ }
+ delete me;
+ return false;
+}
+
+QGraphicsSceneMouseEvent *QSimpleCanvasPrivate::mouseEventToSceneMouseEvent(QMouseEvent *e, const QPoint &item)
+{
+ QEvent::Type t;
+ switch(e->type()) {
+ default:
+ case QEvent::MouseButtonPress:
+ t = QEvent::GraphicsSceneMousePress;
+ break;
+ case QEvent::MouseButtonRelease:
+ t = QEvent::GraphicsSceneMouseRelease;
+ break;
+ case QEvent::MouseMove:
+ t = QEvent::GraphicsSceneMouseMove;
+ break;
+ case QEvent::MouseButtonDblClick:
+ t = QGraphicsSceneEvent::GraphicsSceneMouseDoubleClick;
+ break;
+ }
+
+ QGraphicsSceneMouseEvent *me = new QGraphicsSceneMouseEvent(t);
+ me->setButton(e->button());
+ me->setButtons(e->buttons());
+ me->setModifiers(e->modifiers());
+ me->setPos(item);
+ me->setScreenPos(e->pos());
+ me->setScenePos(e->pos());
+ return me;
+}
+
+bool QSimpleCanvasPrivate::deliverMousePress(QSimpleCanvasItem *base, QMouseEvent *e, bool seenChildFilter)
+{
+ if (base->clipType()) {
+ QRectF br = base->boundingRect();
+ QPointF pos = base->mapFromScene(e->pos());
+ if (!br.contains(pos.toPoint()))
+ return false;
+ }
+
+ const QList<QSimpleCanvasItem *> &children = base->d_func()->children;
+
+ if (base->options() & QSimpleCanvasItem::ChildMouseFilter)
+ seenChildFilter = true;
+
+ for (int ii = children.count() - 1; ii >= 0; --ii) {
+ if (children.at(ii)->visible() != 0.)
+ if (deliverMousePress(children.at(ii), e, seenChildFilter))
+ return true;
+ }
+
+ if (base->acceptedMouseButtons() & e->button() || base->options() & QSimpleCanvasItem::ChildMouseFilter) {
+
+ QRectF br = base->boundingRect();
+ QPoint pos = base->mapFromScene(e->pos()).toPoint();
+
+ if (br.contains(pos)) {
+ QGraphicsSceneMouseEvent *me = mouseEventToSceneMouseEvent(e, pos);
+
+ sendMouseEvent(base, me);
+ bool isAccepted = me->isAccepted();
+ delete me;
+ if (isAccepted) {
+ lastMouseItem = base;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// Delivers e to item
+void QSimpleCanvasPrivate::sendMouseEvent(QSimpleCanvasItem *item, QGraphicsSceneMouseEvent *e)
+{
+ QSimpleCanvasItem *p = item->parent();
+ while(p) {
+ if (p->options() & QSimpleCanvasItem::ChildMouseFilter) {
+ if (p->mouseFilter(e))
+ return;
+ }
+ p = p->parent();
+ }
+ switch(e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ item->mousePressEvent(e);
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ item->mouseReleaseEvent(e);
+ break;
+ case QEvent::GraphicsSceneMouseMove:
+ item->mouseMoveEvent(e);
+ break;
+ case QEvent::GraphicsSceneMouseDoubleClick:
+ item->mouseDoubleClickEvent(e);
+ break;
+ default:
+ break;
+ }
+}
+
+
+QSimpleCanvasRootLayer::QSimpleCanvasRootLayer(QSimpleCanvas *c)
+: _canvas(c)
+{
+ QSimpleCanvasItem::d_func()->canvas = c;
+ setOptions(IsFocusPanel);
+ update();
+}
+
+
+struct QSimpleCanvasTiming
+{
+ QSimpleCanvasTiming()
+ : time(-1), paintTime(-1), timeBetweenFrames(-1) {}
+ QSimpleCanvasTiming(const QRegion &_r, int _time, int _paintTime,
+ int _timeBetweenFrames)
+ : region(_r), time(_time), paintTime(_paintTime),
+ timeBetweenFrames(_timeBetweenFrames) {}
+ QSimpleCanvasTiming(const QSimpleCanvasTiming &other)
+ : region(other.region), time(other.time), paintTime(other.paintTime),
+ timeBetweenFrames(other.timeBetweenFrames) {}
+ QSimpleCanvasTiming &operator=(const QSimpleCanvasTiming &other) {
+ region = other.region; time = other.time; paintTime = other.paintTime;
+ timeBetweenFrames = other.timeBetweenFrames; return *this;
+ }
+ QRegion region;
+ int time;
+ int paintTime;
+ int timeBetweenFrames;
+};
+
+// XXX
+static CircularList<QSimpleCanvasTiming> gfxCanvasTiming;
+
+void QSimpleCanvasGraphicsView::paintEvent(QPaintEvent *pe)
+{
+ QRegion r = pe->region();
+ int tbf = canvas->frameTimer.restart();
+
+ canvas->lrpTimer.start();
+ QGraphicsView::paintEvent(pe);
+ canvas->lrpTime = canvas->lrpTimer.elapsed();
+
+ int frametimer = canvas->frameTimer.elapsed();
+ gfxCanvasTiming.append(QSimpleCanvasTiming(r, frametimer, canvas->lrpTime, tbf));
+ canvas->lrpTime = 0;
+ if (canvas->canvasServer)
+ canvas->canvasServer->addTiming(canvas->lrpTime, frametimer, tbf);
+}
+
+void QSimpleCanvasGraphicsView::focusInEvent(QFocusEvent *)
+{
+}
+
+/*!
+ \internal
+ \class QSimpleCanvas
+ \brief The QSimpleCanvas class implements the canvas used by Qt Declarative
+ */
+
+QSimpleCanvas::QSimpleCanvas(CanvasMode mode, QWidget *parent)
+: QWidget(parent), d(new QSimpleCanvasPrivate(this))
+{
+ d->init(mode);
+}
+
+QSimpleCanvas::QSimpleCanvas(QWidget *parent)
+: QWidget(parent), d(new QSimpleCanvasPrivate(this))
+{
+ d->init(useSimpleCanvas()?SimpleCanvas:GraphicsView);
+}
+
+void QSimpleCanvasPrivate::init(QSimpleCanvas::CanvasMode mode)
+{
+ this->mode = mode;
+
+ if (mode == QSimpleCanvas::SimpleCanvas)
+ qWarning("QSimpleCanvas: Using simple canvas");
+ else
+ qWarning("QSimpleCanvas: Using GraphicsView canvas");
+
+ if (fullUpdate())
+ qWarning("QSimpleCanvas: Full update enabled");
+ if (continuousUpdate())
+ qWarning("QSimpleCanvas: Continuous update enabled");
+
+ QByteArray env = qgetenv("GFX_CANVAS_SERVER_PORT");
+ if (!env.isEmpty()){
+ int port = env.toInt();
+ if (port >= 1024)
+ canvasServer = new QSimpleCanvasServer(port, q);
+ }
+
+ root = new QSimpleCanvasRootLayer(q);
+ root->setActiveFocusPanel(true);
+ q->setFocusPolicy(Qt::StrongFocus);
+
+ if (mode == QSimpleCanvas::GraphicsView) {
+ view = new QSimpleCanvasGraphicsView(this);
+ QHBoxLayout *layout = new QHBoxLayout(q);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0, 0, 0, 0);
+ q->setLayout(layout);
+ layout->addWidget(view);
+ view->setOptimizationFlags(QGraphicsView::DontSavePainterState);
+ view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view->setFrameStyle(0);
+ static_cast<QSimpleCanvasItemPrivate*>(root->d_ptr)->convertToGraphicsItem();
+ view->scene()->addItem(static_cast<QSimpleCanvasItemPrivate*>(root->d_ptr)->graphicsItem);
+
+ // These seem to give the best performance
+ view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+ view->scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
+ view->viewport()->setFocusPolicy(Qt::NoFocus);
+ }
+
+#if defined(QFX_RENDER_OPENGL) && defined(Q_WS_X11)
+ QTimer *t = new QTimer(q);
+ t->setInterval(200);
+ QObject::connect(t, SIGNAL(timeout()), &egl, SLOT(updateGL()));
+ t->start();
+#endif
+}
+
+QSimpleCanvas::~QSimpleCanvas()
+{
+ delete d->root;
+ delete d;
+}
+
+void QSimpleCanvasPrivate::paint(QPainter &p)
+{
+#if defined(QFX_RENDER_QPAINTER)
+ if (!isSetup)
+ root->d_func()->setupPainting(0, q->rect());
+
+ lrpTimer.start();
+
+ root->d_func()->paint(p);
+
+ lrpTime = lrpTimer.elapsed();
+#else
+ Q_UNUSED(p);
+#endif
+}
+
+QSimpleCanvas::CanvasMode QSimpleCanvas::canvasMode() const
+{
+ return d->mode;
+}
+
+QSimpleCanvasItem *QSimpleCanvas::root()
+{
+ return d->root;
+}
+
+void QSimpleCanvas::keyPressEvent(QKeyEvent *event)
+{
+ if (d->focusItem)
+ d->focusItem->keyPressEvent(event);
+ QWidget::keyPressEvent(event);
+}
+
+void QSimpleCanvas::keyReleaseEvent(QKeyEvent *event)
+{
+ if (d->focusItem)
+ d->focusItem->keyReleaseEvent(event);
+ QWidget::keyReleaseEvent(event);
+}
+
+void QSimpleCanvas::inputMethodEvent(QInputMethodEvent *event)
+{
+ if (d->focusItem)
+ d->focusItem->inputMethodEvent(event);
+ else
+ QWidget::inputMethodEvent(event);
+}
+
+QVariant QSimpleCanvas::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ if (d->focusItem)
+ return d->focusItem->inputMethodQuery(query);
+ return QWidget::inputMethodQuery(query);
+}
+
+void QSimpleCanvas::mousePressEvent(QMouseEvent *e)
+{
+ if (d->isSimpleCanvas() &&
+ (d->filter(e) || d->deliverMousePress(d->root, e))) {
+ e->accept();
+ } else {
+ QWidget::mousePressEvent(e);
+ }
+}
+
+void QSimpleCanvas::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ if (d->isSimpleCanvas() &&
+ (d->filter(e) || d->deliverMousePress(d->root, e))) {
+ e->accept();
+ } else {
+ QWidget::mouseDoubleClickEvent(e);
+ }
+}
+
+void QSimpleCanvas::mouseMoveEvent(QMouseEvent *e)
+{
+ if (d->isSimpleCanvas() && d->filter(e)) {
+ e->accept();
+ } else if (d->isSimpleCanvas() && d->lastMouseItem) {
+ QPoint p = d->lastMouseItem->mapFromScene(e->pos()).toPoint();
+ QGraphicsSceneMouseEvent *me = d->mouseEventToSceneMouseEvent(e, p);
+ d->sendMouseEvent(d->lastMouseItem, me);
+ e->setAccepted(me->isAccepted());
+ delete me;
+ } else {
+ QWidget::mouseMoveEvent(e);
+ }
+}
+
+void QSimpleCanvas::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (d->isSimpleCanvas() && d->filter(e)) {
+ e->accept();
+ } else if (d->isSimpleCanvas() && d->lastMouseItem) {
+ QPoint p = d->lastMouseItem->mapFromScene(e->pos()).toPoint();
+ QGraphicsSceneMouseEvent *me = d->mouseEventToSceneMouseEvent(e, p);
+ d->sendMouseEvent(d->lastMouseItem, me);
+ d->lastMouseItem->mouseUngrabEvent();
+ e->setAccepted(me->isAccepted());
+ delete me;
+ d->lastMouseItem = 0;
+ } else {
+ QWidget::mouseReleaseEvent(e);
+ }
+}
+
+void QSimpleCanvas::focusInEvent(QFocusEvent *event)
+{
+ // XXX
+#if 0
+ if (d->lastFocusItem && event->reason() == Qt::ActiveWindowFocusReason) {
+ d->setFocusItem(d->lastFocusItem, event->reason());
+ } else {
+ QSimpleCanvasItem *panel = activeFocusPanel();
+ QSimpleCanvasItem *focusItem = 0;
+ if (panel->isFocusable())
+ focusItem = panel;
+ else
+ focusItem = QSimpleCanvasItem::findNextFocus(panel);
+
+ if (focusItem)
+ d->setFocusItem(focusItem, event->reason());
+ else
+ QWidget::focusNextPrevChild(true);
+ }
+#endif
+ QWidget::focusInEvent(event);
+}
+
+void QSimpleCanvas::focusOutEvent(QFocusEvent *event)
+{
+ // XXX
+#if 0
+ if (event->reason() == Qt::ActiveWindowFocusReason) {
+ d->lastFocusItem = activeFocusPanel();
+ d->setActiveFocusPanel(0, Qt::ActiveWindowFocusReason);
+ }
+#endif
+ QWidget::focusOutEvent(event);
+}
+
+bool QSimpleCanvas::focusNextPrevChild(bool)
+{
+ // XXX
+#if 0
+ if (d->focusItem) {
+ QSimpleCanvasItem *item = next ? QSimpleCanvasItem::findNextFocus(d->focusItem) : QSimpleCanvasItem::findPrevFocus(d->focusItem);
+ if (item) {
+ d->setFocusItem(item,
+ next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+ return true;
+ }
+ }
+
+ QSimpleCanvasItem *panel = activeFocusPanel();
+ QSimpleCanvasItem *item = 0;
+ if (panel->isFocusable())
+ item = panel;
+ else
+ item = next ? QSimpleCanvasItem::findNextFocus(panel) : QSimpleCanvasItem::findPrevFocus(panel);
+ if (item && item != d->focusItem) {
+ d->setFocusItem(item,
+ next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+ return true;
+ }
+
+ if (d->focusItem)
+ d->setActiveFocusPanel(0, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+
+#endif
+ return false;
+}
+
+
+void QSimpleCanvas::showEvent(QShowEvent *e)
+{
+#if defined(QFX_RENDER_OPENGL)
+ d->egl.resize(width(), height());
+#endif
+ if (d->isGraphicsView())
+ d->view->setSceneRect(rect());
+
+ QWidget::showEvent(e);
+}
+
+void QSimpleCanvas::resizeEvent(QResizeEvent *e)
+{
+#if defined(QFX_RENDER_OPENGL)
+ d->egl.resize(width(), height());
+#endif
+ if (d->isGraphicsView())
+ d->view->setSceneRect(rect());
+ QWidget::resizeEvent(e);
+}
+
+
+void QSimpleCanvas::remDirty(QSimpleCanvasItem *c)
+{
+ d->dirtyItems.removeAll(c);
+}
+
+void QSimpleCanvas::queueUpdate()
+{
+ if (!d->timer) {
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ d->timer = 1;
+ }
+}
+
+void QSimpleCanvas::addDirty(QSimpleCanvasItem *c)
+{
+ queueUpdate();
+ if (d->isSimpleCanvas()) {
+ d->oldDirty |= c->d_func()->data()->lastPaintRect;
+#if defined(QFX_RENDER_OPENGL)
+ // Check for filters
+ QSimpleCanvasItem *fi = c->parent();
+ while(fi) {
+ if (fi->d_func()->data()->dirty) {
+ break;
+ } else if (fi->filter()) {
+ fi->update();
+ break;
+ }
+ fi = fi->parent();
+ }
+#endif
+ d->dirtyItems.append(c);
+ }
+}
+
+QRect QSimpleCanvasPrivate::dirtyItemClip() const
+{
+ QRect rv;
+ if (isSimpleCanvas()) {
+#if defined(QFX_RENDER_OPENGL)
+ QRectF r;
+ for (int ii = 0; ii < dirtyItems.count(); ++ii)
+ r |= dirtyItems.at(ii)->d_func()->data()->lastPaintRect;
+ rv = egl.map(r);
+#else
+ for (int ii = 0; ii < dirtyItems.count(); ++ii)
+ rv |= dirtyItems.at(ii)->d_func()->data()->lastPaintRect;
+#endif
+ }
+ return rv;
+}
+
+QRegion QSimpleCanvasPrivate::resetDirty()
+{
+ if (isSimpleCanvas()) {
+#if defined(QFX_RENDER_OPENGL)
+ QRect r = egl.map(oldDirty) | dirtyItemClip();
+#else
+ QRect r = oldDirty | dirtyItemClip();
+#endif
+ if (!r.isEmpty())
+ r.adjust(-1,-1,2,2); //make sure we get everything (since we rounded from floats to ints)
+ for (int ii = 0; ii < dirtyItems.count(); ++ii)
+ static_cast<QSimpleCanvasItemPrivate*>(dirtyItems.at(ii)->d_ptr)->data()->dirty = false;
+ dirtyItems.clear();
+ oldDirty = QRect();
+
+ if (fullUpdate())
+ return QRegion();
+ else
+ return QRegion(r);
+ } else {
+ return QRegion();
+ }
+}
+
+QSimpleCanvasItem *QSimpleCanvas::focusItem() const
+{
+ return d->focusItem;
+}
+
+QSimpleCanvasItem *QSimpleCanvas::activeFocusPanel() const
+{
+ if (d->focusPanels.isEmpty())
+ return 0;
+ else
+ return d->focusPanels.top();
+}
+
+QSimpleCanvasItem *QSimpleCanvas::focusItem(QSimpleCanvasItem *item) const
+{
+ while (item && d->focusPanelData.contains(item))
+ item = d->focusPanelData.value(item);
+ return item;
+}
+
+bool QSimpleCanvas::event(QEvent *e)
+{
+ if (e->type() == QEvent::User && d->isSimpleCanvas()) {
+ d->timer = 0;
+ d->isSetup = true;
+#if defined(QFX_RENDER_OPENGL1)
+ unsigned int zero = 0;
+ d->root->d_func()->setupPainting(0, rect(), &zero);
+#else
+ d->root->d_func()->setupPainting(0, rect());
+#endif
+
+ QRegion r = d->resetDirty();
+
+ int tbf = d->frameTimer.restart();
+
+#if defined(QFX_RENDER_QPAINTER)
+ if (r.isEmpty() || fullUpdate())
+ repaint();
+ else
+ repaint(r);
+ emit framePainted();
+#else
+ QRect br = r.boundingRect();
+ QRect nr(br.x(), height() - br.y() - br.height(), br.width(), br.height());
+
+ if (r.isEmpty() || fullUpdate())
+ d->egl.updateGL();
+ else
+ d->egl.updateGL(nr);
+ emit framePainted();
+#endif
+ d->isSetup = false;
+
+ int frametimer = d->frameTimer.elapsed();
+ gfxCanvasTiming.append(QSimpleCanvasTiming(r, frametimer, d->lrpTime, tbf));
+ if (d->canvasServer)
+ d->canvasServer->addTiming(d->lrpTime, frametimer, tbf);
+ d->lrpTime = 0;
+ if (continuousUpdate())
+ queueUpdate();
+
+ return true;
+ } else {
+ return QWidget::event(e);
+ }
+}
+
+void QSimpleCanvas::paintEvent(QPaintEvent *)
+{
+#if defined(QFX_RENDER_QPAINTER)
+ if (d->mode == SimpleCanvas) {
+ QPainter p(this);
+ d->paint(p);
+ }
+#endif
+}
+
+void QSimpleCanvas::dumpTiming()
+{
+ for (int ii = 0; ii < gfxCanvasTiming.size(); ++ii) {
+ const QSimpleCanvasTiming &t = gfxCanvasTiming[ii];
+
+ qreal repaintFps = 1000. / qreal(t.time);
+ qreal paintFps = 1000. / qreal(t.paintTime);
+ qreal tbfFps = 1000. / qreal(t.timeBetweenFrames);
+
+ qWarning() << "repaint():" << t.time << "ms," << repaintFps << "fps. paint():" << t.paintTime << "ms," << paintFps << "fps. timeSinceLastFrame:" << t.timeBetweenFrames << "ms," << tbfFps << "fps.";
+ qWarning() << t.region;
+ }
+ gfxCanvasTiming.clear();
+}
+
+void QSimpleCanvas::dumpItems()
+{
+ int items = d->root->d_func()->dump(0);
+ qWarning() << "Total:" << items;
+}
+
+void QSimpleCanvas::checkState()
+{
+ if (d->isSimpleCanvas()) {
+ QSimpleCanvasItemPrivate::FocusStateCheckRDatas r;
+ if (d->root->d_func()->checkFocusState(0, &r))
+ qWarning() << "State OK";
+ }
+}
+
+/*!
+ Returns canvas as an image. Not a fast operation.
+*/
+QImage QSimpleCanvas::asImage() const
+{
+ if (d->isSimpleCanvas()) {
+#if defined(QFX_RENDER_QPAINTER)
+ QImage img(width(),height(),QImage::Format_RGB32);
+ QPainter p(&img);
+ const_cast<QSimpleCanvas*>(this)->d->paint(p);
+ return img;
+#elif defined(QFX_RENDER_OPENGL)
+ return d->egl.grabFrameBuffer();
+#endif
+ } else {
+ QImage img(width(),height(),QImage::Format_RGB32);
+ QPainter p(&img);
+ d->view->render(&p);
+ return img;
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas.h b/src/declarative/canvas/qsimplecanvas.h
new file mode 100644
index 0000000..d57ada4
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVAS_H
+#define QSIMPLECANVAS_H
+
+#include <qfxglobal.h>
+
+#ifdef QFX_RENDER_OPENGL
+#include <QtGui/qmatrix4x4.h>
+#endif
+
+#include <QtGui/QTransform>
+#include <QtGui/QPainter>
+#include <QtCore/QDebug>
+#include <QtGui/QWidget>
+#include <QtGui/QImage>
+#include <QtGui/QKeyEvent>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+namespace QSimpleCanvasConfig
+{
+ enum ImageType { Opaque, Translucent };
+
+#ifdef QFX_RENDER_OPENGL
+ typedef QMatrix4x4 Matrix;
+ typedef QImage Image;
+
+ inline Matrix transformToMatrix(const QTransform &)
+ {
+ return Matrix(); // XXX
+ }
+ inline QTransform matrixToTransform(const Matrix &)
+ {
+ return QTransform(); // XXX
+ }
+ inline bool needConvert(ImageType, const Image &)
+ { return false; }
+ inline Image convert(ImageType, const Image &i)
+ { return i; }
+ inline Image create(const QSize &s)
+ { return QImage(s, QImage::Format_ARGB32); }
+ inline const Image &toImage(const QImage &i)
+ { return i; }
+
+#elif defined(QFX_RENDER_QPAINTER)
+ typedef QTransform Matrix;
+ typedef QImage Image;
+
+ inline Matrix transformToMatrix(const QTransform &t)
+ { return t; }
+ inline QTransform matrixToTransform(const Matrix &t)
+ { return t; }
+ inline bool needConvert(ImageType type, const Image &img) {
+ QImage::Format f = img.format();
+ return !((type == Opaque && f == QImage::Format_RGB16) ||
+ (type == Translucent && f == QImage::Format_ARGB32_Premultiplied));
+ }
+ inline Image convert(ImageType type, const Image &img) {
+ if (type == Opaque)
+ return img.convertToFormat(QImage::Format_RGB16);
+ else
+ return img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ }
+ inline Image create(const QSize &s)
+ { return QImage(s, QImage::Format_ARGB32_Premultiplied); }
+ inline const Image &toImage(const QImage &i)
+ { return i; }
+#endif
+}
+
+class QSimpleCanvas;
+class QSimpleCanvasLayer;
+
+class QGraphicsSceneMouseEvent;
+class GLBasicShaders;
+class QSimpleCanvasItem;
+class QSimpleCanvasPrivate;
+class Q_DECLARATIVE_EXPORT QSimpleCanvas : public QWidget
+{
+Q_OBJECT
+public:
+ typedef QSimpleCanvasConfig::Matrix Matrix;
+
+ enum CanvasMode { GraphicsView, SimpleCanvas };
+
+ QSimpleCanvas(QWidget *parent = 0);
+ QSimpleCanvas(CanvasMode, QWidget *parent = 0);
+ virtual ~QSimpleCanvas();
+
+ CanvasMode canvasMode() const;
+
+ QSimpleCanvasItem *root();
+
+ // Debugging
+ void dumpTiming();
+ void dumpItems();
+ void checkState();
+
+ QSimpleCanvasItem *focusItem() const;
+ QSimpleCanvasItem *focusItem(QSimpleCanvasItem *item) const;
+
+ QSimpleCanvasItem *activeFocusPanel() const;
+ QImage asImage() const;
+
+Q_SIGNALS:
+ void framePainted();
+
+protected:
+ virtual bool event(QEvent *);
+ virtual void paintEvent(QPaintEvent *);
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void mouseDoubleClickEvent(QMouseEvent *);
+ virtual void mouseMoveEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void focusInEvent(QFocusEvent *event);
+ virtual void focusOutEvent(QFocusEvent *event);
+ virtual bool focusNextPrevChild(bool next);
+ virtual bool eventFilter(QObject *obj, QEvent *event);
+ virtual void inputMethodEvent(QInputMethodEvent *event);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+
+ virtual void showEvent(QShowEvent *);
+ virtual void resizeEvent(QResizeEvent *);
+private:
+
+ friend class QSimpleCanvasRootLayer;
+ friend class QSimpleCanvasPrivate;
+ friend class QSimpleCanvasItem;
+ friend class QSimpleCanvasItemPrivate;
+ friend class QSimpleCanvasFilter;
+ friend class QSimpleGraphicsItem;
+
+ void queueUpdate();
+ QSimpleCanvasPrivate *d;
+ void addDirty(QSimpleCanvasItem *);
+ void remDirty(QSimpleCanvasItem *);
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/canvas/qsimplecanvas_graphicsview.cpp b/src/declarative/canvas/qsimplecanvas_graphicsview.cpp
new file mode 100644
index 0000000..dd4012b
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_graphicsview.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvas.h"
+#include "qsimplecanvas_p.h"
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvasitem_p.h"
+#include <QGraphicsItem>
+#include <QGraphicsSceneMouseEvent>
+
+
+QT_BEGIN_NAMESPACE
+static QHash<QGraphicsScene*,QSimpleCanvas*> sceneMap;
+
+QSimpleCanvasGraphicsView::QSimpleCanvasGraphicsView(QSimpleCanvasPrivate *parent)
+: QGraphicsView(parent->q), canvas(parent)
+{
+ setScene(&_scene);
+ sceneMap[&_scene] = parent->q;
+ setFrameShape(QFrame::NoFrame);
+ viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
+}
+
+QSimpleCanvasGraphicsView::~QSimpleCanvasGraphicsView()
+{
+ sceneMap.remove(&_scene);
+}
+
+QSimpleGraphicsItem::QSimpleGraphicsItem(QSimpleCanvasItem *canvasItem)
+: /*scene(0),*/ owner(canvasItem)
+{
+ setAcceptedMouseButtons(Qt::NoButton);
+}
+
+QSimpleGraphicsItem::~QSimpleGraphicsItem()
+{
+ owner->d_func()->graphicsItem = 0;
+}
+
+void QSimpleGraphicsItem::paint(QPainter *painter,
+ const QStyleOptionGraphicsItem *, QWidget *)
+{
+ owner->paintContents(*painter);
+}
+
+QRectF QSimpleGraphicsItem::boundingRect() const
+{
+ return owner->boundingRect();
+}
+
+void QSimpleGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ QSimpleCanvasItem *p = owner->parent();
+ while(p) {
+ if (p->options() & QSimpleCanvasItem::ChildMouseFilter) {
+ if (p->mouseFilter(event))
+ return;
+ }
+ p = p->parent();
+ }
+ owner->mousePressEvent(event);
+}
+
+void QSimpleGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ QSimpleCanvasItem *p = owner->parent();
+ while(p) {
+ if (p->options() & QSimpleCanvasItem::ChildMouseFilter) {
+ if (p->mouseFilter(event))
+ return;
+ }
+ p = p->parent();
+ }
+ owner->mouseReleaseEvent(event);
+ ungrabMouse();
+}
+
+void QSimpleGraphicsItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ QSimpleCanvasItem *p = owner->parent();
+ while(p) {
+ if (p->options() & QSimpleCanvasItem::ChildMouseFilter) {
+ if (p->mouseFilter(event))
+ return;
+ }
+ p = p->parent();
+ }
+ owner->mouseDoubleClickEvent(event);
+}
+
+void QSimpleGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ QSimpleCanvasItem *p = owner->parent();
+ while(p) {
+ if (p->options() & QSimpleCanvasItem::ChildMouseFilter) {
+ if (p->mouseFilter(event))
+ return;
+ }
+ p = p->parent();
+ }
+ owner->mouseMoveEvent(event);
+}
+
+bool QSimpleGraphicsItem::sceneEvent(QEvent *event)
+{
+ bool rv = QGraphicsItem::sceneEvent(event);
+ if (event->type() == QEvent::UngrabMouse)
+ owner->mouseUngrabEvent();
+ return rv;
+}
+
+QVariant QSimpleGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ if (change == ItemSceneHasChanged) {
+ QSimpleCanvasItemPrivate *owner_d = static_cast<QSimpleCanvasItemPrivate*>(owner->d_ptr);
+ QSimpleCanvas *oldCanvas = owner_d->canvas;
+ owner_d->canvas = sceneMap[scene()];
+ if (owner_d->canvas){
+ if (owner->hasFocus())
+ owner->canvas()->d->setFocusItem(owner, Qt::OtherFocusReason);
+ if (owner->options() & QSimpleCanvasItem::IsFocusPanel) {
+ if (owner_d->wantsActiveFocusPanelPendingCanvas) {
+ owner_d->hasBeenActiveFocusPanel = true;
+ owner->canvas()->d->setActiveFocusPanel(owner);
+ owner_d->wantsActiveFocusPanelPendingCanvas = false;
+ }
+ }
+ }
+ if (owner->options() & QSimpleCanvasItem::MouseFilter)
+ owner_d->gvRemoveMouseFilter();
+
+ if (oldCanvas != owner_d->canvas)
+ owner->canvasChanged();
+
+ if (owner->options() & QSimpleCanvasItem::MouseFilter)
+ owner_d->gvAddMouseFilter();
+ }
+
+ return QGraphicsItem::itemChange(change, value);
+}
+
+void QSimpleGraphicsItem::keyPressEvent(QKeyEvent *event)
+{
+ owner->keyPressEvent(event);
+ QGraphicsItem::keyPressEvent(event);
+}
+
+void QSimpleGraphicsItem::keyReleaseEvent(QKeyEvent *event)
+{
+ owner->keyReleaseEvent(event);
+ QGraphicsItem::keyReleaseEvent(event);
+}
+
+void QSimpleGraphicsItem::focusInEvent(QFocusEvent *)
+{
+ if (!owner->hasFocus())
+ owner->setFocus(true);
+}
+
+void QSimpleCanvasItemPrivate::gvRemoveMouseFilter()
+{
+ QGraphicsScene *scene = graphicsItem->scene();
+ if (!scene) return;
+
+ scene->removeEventFilter(q_ptr);
+}
+
+void QSimpleCanvasItemPrivate::gvAddMouseFilter()
+{
+ QGraphicsScene *scene = graphicsItem->scene();
+ if (!scene) return;
+
+ scene->installEventFilter(q_ptr);
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas_opengl.cpp b/src/declarative/canvas/qsimplecanvas_opengl.cpp
new file mode 100644
index 0000000..98f92d7
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_opengl.cpp
@@ -0,0 +1,456 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvas.h"
+#include "qsimplecanvas_p.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvasfilter_p.h"
+#include <glsave.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#include <gltexture.h>
+#include <math.h>
+
+
+QT_BEGIN_NAMESPACE
+void CanvasEGLWidget::paintGL()
+{
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ _canvas->paintGL();
+}
+
+void CanvasEGLWidget::updateGL()
+{
+ _clip = QRect();
+ QGLWidget::updateGL();
+}
+
+void CanvasEGLWidget::updateGL(const QRect &r)
+{
+ if (r.isEmpty())
+ return;
+
+ _clip = r;
+ QGLWidget::updateGL();
+}
+
+void CanvasEGLWidget::resizeGL(int w, int h)
+{
+ glViewport(0, 0, w, h);
+}
+
+QRect CanvasEGLWidget::map(const QRectF &f) const
+{
+ return invDefaultTransform.mapRect(f).toAlignedRect();
+}
+
+void CanvasEGLWidget::resizeEvent(QResizeEvent *e)
+{
+ defaultTransform.setIdentity();
+ defaultTransform.flipCoordinates();
+ defaultTransform.translate(-1, -1, 0);
+ defaultTransform.scale(2. / width(), 2. / height(), 1. / (1024. * 1024.));
+ invDefaultTransform = defaultTransform.inverted();
+ _canvas->root->d_func()->data()->transformActive = defaultTransform;
+ _canvas->root->d_func()->data()->transformValid = true;
+
+ QGLWidget::resizeEvent(e);
+}
+
+void CanvasEGLWidget::initializeGL()
+{
+ glEnable(GL_BLEND);
+ glEnable(GL_STENCIL_TEST);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glStencilFunc(GL_EQUAL, 0, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+}
+
+void QSimpleCanvasPrivate::paintGL()
+{
+ lrpTimer.start();
+
+ QSimpleCanvasItemPrivate::GLPaintParameters p;
+ p.sceneRect = QRect(0, 0, q->width(), q->height());
+ p.clipRect = p.sceneRect;
+ p.stencilValue = 0;
+ p.opacity = 1;
+ p.forceParamRefresh = false;
+ if (!isSetup)
+ root->d_func()->setupPainting(0, QRect());
+ root->d_func()->paint(p);
+
+ lrpTime = lrpTimer.elapsed();
+}
+
+QGLFramebufferObject *QSimpleCanvasPrivate::acquire(int w, int h)
+{
+ if (w <= 0 || h <= 0)
+ return 0;
+
+ int size = qMax(w, h);
+ for (int ii = 0; ii < frameBuffers.count(); ++ii) {
+ if (frameBuffers.at(ii)->width() >= size) {
+ QGLFramebufferObject *rv = frameBuffers.at(ii);
+ frameBuffers.removeAt(ii);
+ return rv;
+ }
+ }
+
+ // Find power of two
+ size--;
+ size |= size >> 1;
+ size |= size >> 2;
+ size |= size >> 4;
+ size |= size >> 8;
+ size |= size >> 16;
+ size++;
+
+ QGLFramebufferObject *fbo = new QGLFramebufferObject(size, size);
+ return fbo;
+}
+
+void QSimpleCanvasPrivate::release(QGLFramebufferObject *buf)
+{
+ int size = qMax(buf->width(), buf->height());
+ for (int ii = 0; ii < frameBuffers.count(); ++ii) {
+ if (frameBuffers.at(ii)->width() >= size) {
+ frameBuffers.insert(ii, buf);
+ return;
+ }
+ }
+ frameBuffers.append(buf);
+}
+
+GLBasicShaders *QSimpleCanvasItemPrivate::basicShaders() const
+{
+ return canvas->d->basicShaders();
+}
+
+QSimpleCanvas::Matrix QSimpleCanvasItemPrivate::localTransform() const
+{
+ Q_Q(const QSimpleCanvasItem);
+
+ QSimpleCanvas::Matrix trans;
+ trans.translate(q->x(), q->y());
+ QPointF to = transformOrigin();
+ trans.translate(to.x(), to.y());
+ trans.scale(q->scale(), q->scale());
+ trans.translate(-to.x(), -to.y());
+ if (data()->transformUser)
+ trans *= *data()->transformUser;
+ return trans;
+}
+
+void QSimpleCanvasItemPrivate::simplePaintChild(const GLPaintParameters &params, QSimpleCanvasItem *child)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ GLPaintParameters childParams = params;
+ if (clip)
+ ++childParams.stencilValue;
+
+ if (child->d_func()->data()->activeOpacity != 0) {
+ childParams.boundingRect = child->boundingRect();
+
+ if (child->filter() && child->filter()->enabled()) {
+ QSimpleCanvasItem::GLPainter painter(q);
+ painter.activeTransform = child->d_func()->data()->transformActive;
+ painter.activeOpacity = child->d_func()->data()->activeOpacity;
+ painter.sceneClipRect = params.clipRect;
+ child->filter()->d->doFilterGL(painter, childParams);
+ } else {
+ child->d_func()->paint(childParams);
+ }
+ }
+}
+
+void QSimpleCanvasItemPrivate::paintChild(const GLPaintParameters &params,
+ QSimpleCanvasItem *child)
+{
+ if (params.forceParamRefresh) {
+ QSimpleCanvas::Matrix t = child->d_func()->data()->transformActive;
+ qreal o = child->d_func()->data()->activeOpacity;
+ setupChildState(child);
+ simplePaintChild(params, child);
+ child->d_func()->data()->transformActive = t;
+ child->d_func()->data()->transformValid = true;
+ child->d_func()->data()->activeOpacity = o;
+ } else {
+ simplePaintChild(params, child);
+ }
+}
+
+void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child)
+{
+ qreal visible = child->visible();
+ child->d_func()->data()->activeOpacity = data()->activeOpacity;
+ if (visible != 1)
+ child->d_func()->data()->activeOpacity *= visible;
+
+ if (child->d_func()->data()->activeOpacity != 0) {
+ // Calculate child's transform
+ qreal x = child->x();
+ qreal y = child->y();
+ qreal scale = child->scale();
+ QSimpleCanvasItem::Flip flip = child->flip();
+
+ QSimpleCanvas::Matrix &am = child->d_func()->data()->transformActive;
+ am = data()->transformActive;
+ if (x != 0 || y != 0)
+ am.translate(x, y);
+ if (scale != 1) {
+ QPointF to = child->d_func()->transformOrigin();
+ if (to.x() != 0. || to.y() != 0.)
+ am.translate(to.x(), to.y());
+ am.scale(scale, scale);
+ if (to.x() != 0. || to.y() != 0.)
+ am.translate(-to.x(), -to.y());
+ }
+ if (child->d_func()->data()->transformUser)
+ am *= *child->d_func()->data()->transformUser;
+ if (flip) {
+ QRectF br = child->boundingRect();
+ am.translate(br.width() / 2., br.height() / 2);
+ am.rotate(180, (flip & QSimpleCanvasItem::VerticalFlip)?1:0, (flip & QSimpleCanvasItem::HorizontalFlip)?1:0, 0);
+ am.translate(-br.width() / 2., -br.height() / 2);
+ }
+ child->d_func()->data()->transformValid = true;
+ }
+}
+
+QRectF QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &bounding)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ QRectF filteredBoundRect = q->boundingRect();
+ if (filter)
+ filteredBoundRect = filter->itemBoundingRect(filteredBoundRect);
+ QRectF rv = data()->transformActive.mapRect(filteredBoundRect);
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QSimpleCanvasItem *child = children.at(ii);
+ setupChildState(child);
+
+ if (child->d_func()->data()->activeOpacity != 0)
+ rv |= child->d_func()->setupPainting(version, bounding);
+ }
+
+ data()->lastPaintRect = rv;
+ return rv;
+}
+
+void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvasFilter::Layer layer)
+{
+ if (!layer)
+ return;
+
+ Q_Q(QSimpleCanvasItem);
+
+ GLPaintParameters params = oldParams;
+
+ qreal width = params.boundingRect.width();
+ qreal height = params.boundingRect.height();
+
+ GLfloat vertices[] = { 0, height,
+ width, height,
+ 0, 0,
+ width, 0 };
+
+ // XXX Handle separate cliping modes
+ if (clip) {
+ if (params.stencilValue == 255)
+ qWarning()
+ << "OpenGL: Clip recursion greater than 255 not permitted.";
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ glStencilFunc(GL_EQUAL, params.stencilValue, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+
+ ConstantColorShader *shader = basicShaders()->constantColor();
+ shader->enable();
+ shader->setTransform(data()->transformActive);
+
+ shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(ConstantColorShader::Vertices);
+
+ glStencilFunc(GL_EQUAL, params.stencilValue + 1, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ // XXX Copied from qsimplecanvas_opengl1 scissor based clipping
+ QRectF r = data()->transformActive.mapRect(params.boundingRect);
+ r.translate(1, 1);
+ float xscale = 0.5 * float(params.sceneRect.width());
+ float yscale = 0.5 * float(params.sceneRect.height());
+ r.moveTo(r.x() * xscale, r.y() * yscale);
+ r.setSize(QSizeF(r.width() * xscale, r.height() * yscale));
+ int sr_x = int(::floorf(r.x()));
+ int sr_y = int(::floorf(r.y()));
+ int sr_width = int(::ceilf(r.right())) - sr_x;
+ int sr_height = int(::ceilf(r.bottom())) - sr_y;
+ QRect sr(sr_x, sr_y, sr_width, sr_height);
+ sr.moveTo(sr.x(), params.sceneRect.height() - sr.y() - sr.height());
+ sr &= params.clipRect;
+ params.clipRect = sr;
+ }
+
+ zOrderChildren();
+
+ int upto = 0;
+ for (upto = 0; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ if (c->z() < 0) {
+ if (layer & QSimpleCanvasFilter::ChildrenUnderItem)
+ paintChild(params, c);
+ } else {
+ break;
+ }
+ }
+
+ if (layer & QSimpleCanvasFilter::Item &&
+ q->options() & QSimpleCanvasItem::HasContents) {
+ QSimpleCanvasItem::GLPainter painter(q);
+ painter.activeTransform = data()->transformActive;
+ painter.activeOpacity = data()->activeOpacity;
+ painter.sceneClipRect = params.clipRect;
+
+ q->paintGLContents(painter);
+ }
+
+ if (layer & QSimpleCanvasFilter::ChildrenAboveItem) {
+ for (; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ paintChild(params, c);
+ }
+ }
+
+ if (clip) {
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glStencilFunc(GL_EQUAL, params.stencilValue + 1, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
+
+ ConstantColorShader *shader = basicShaders()->constantColor();
+ shader->enable();
+ shader->setTransform(data()->transformActive);
+
+ shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(ConstantColorShader::Vertices);
+
+ glStencilFunc(GL_EQUAL, params.stencilValue, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+}
+
+QGLShaderProgram *QSimpleCanvasItem::GLPainter::useTextureShader()
+{
+ if (activeOpacity == 1.) {
+ item->basicShaders()->singleTexture()->enable();
+ item->basicShaders()->singleTexture()->setTransform(activeTransform);
+ return item->basicShaders()->singleTexture();
+ } else {
+ item->basicShaders()->singleTextureOpacity()->enable();
+ item->basicShaders()->singleTextureOpacity()->setTransform(activeTransform);
+ item->basicShaders()->singleTextureOpacity()->setOpacity(activeOpacity);
+ return item->basicShaders()->singleTextureOpacity();
+ }
+
+}
+
+QGLShaderProgram *QSimpleCanvasItem::GLPainter::useColorShader(const QColor &color)
+{
+ QColor c = color;
+ item->basicShaders()->constantColor()->enable();
+ if (activeOpacity != 1.) {
+ c.setAlpha(int(c.alpha() * activeOpacity));
+ }
+
+ item->basicShaders()->constantColor()->setColor(c);
+ item->basicShaders()->constantColor()->setTransform(activeTransform);
+
+ return item->basicShaders()->constantColor();
+}
+
+void QSimpleCanvasItem::GLPainter::drawImage(const QPointF &point,
+ const GLTexture &texture)
+{
+ drawImage(QRectF(point, QSizeF(texture.width(), texture.height())), texture);
+}
+
+void QSimpleCanvasItem::GLPainter::drawImage(const QRectF &rect,
+ const GLTexture &img)
+{
+ QGLShaderProgram *shader = useTextureShader();
+
+ GLfloat vertices[8];
+ GLfloat texVertices[8];
+
+ float widthV = img.width();
+ float heightV = img.height();
+
+ vertices[0] = rect.x(); vertices[1] = rect.y()+heightV;
+ vertices[2] = rect.x()+widthV; vertices[3] = rect.y()+heightV;
+ vertices[4] = rect.x(); vertices[5] = rect.y();
+ vertices[6] = rect.x()+widthV; vertices[7] = rect.y();
+
+ texVertices[0] = 0; texVertices[1] = 0;
+ texVertices[2] = 1; texVertices[3] = 0;
+ texVertices[4] = 0; texVertices[5] = 1;
+ texVertices[6] = 1; texVertices[7] = 1;
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2);
+
+ glBindTexture(GL_TEXTURE_2D, img.texture());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas_opengl1.cpp b/src/declarative/canvas/qsimplecanvas_opengl1.cpp
new file mode 100644
index 0000000..3fd8490
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_opengl1.cpp
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvas.h"
+#include "qsimplecanvas_p.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvasfilter_p.h"
+#include <gltexture.h>
+#include <glsave.h>
+#include <math.h>
+
+
+QT_BEGIN_NAMESPACE
+void CanvasEGLWidget::updateGL()
+{
+ _clip = QRect();
+ QGLWidget::updateGL();
+}
+
+void CanvasEGLWidget::updateGL(const QRect &r)
+{
+ if (r.isEmpty())
+ return;
+
+ _clip = r;
+ QGLWidget::updateGL();
+}
+
+void CanvasEGLWidget::paintGL()
+{
+ if (!_clip.isEmpty()) {
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(_clip.x(), _clip.y(), _clip.width(), _clip.height());
+ } else {
+ glDisable(GL_SCISSOR_TEST);
+ }
+
+ glDepthMask(GL_TRUE);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glDepthMask(GL_FALSE);
+
+ _canvas->paintGL();
+}
+
+QRect CanvasEGLWidget::map(const QRectF &f)
+{
+ return invDefaultTransform.mapRect(f).toAlignedRect();
+}
+
+void CanvasEGLWidget::resizeGL(int w, int h)
+{
+ glViewport(0, 0, w, h);
+}
+
+void CanvasEGLWidget::resizeEvent(QResizeEvent *e)
+{
+ defaultTransform.identity();
+ defaultTransform.flipCoordinates();
+ defaultTransform.translate(-1, -1, 0);
+ defaultTransform.scale(2. / width(), 2. / height(), -2. / 65536.);
+ invDefaultTransform = defaultTransform.inverted();
+ _canvas->root->d_func()->transformActive = defaultTransform;
+ QGLWidget::resizeEvent(e);
+}
+
+void CanvasEGLWidget::initializeGL()
+{
+ glEnable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDepthFunc(GL_GREATER);
+#ifdef QT_OPENGL_ES
+ glClearDepthf(0);
+#else
+ glClearDepth(0);
+#endif
+}
+
+void QSimpleCanvasPrivate::paintGL()
+{
+ lrpTimer.start();
+
+ QSimpleCanvasItemPrivate::GLPaintParameters p;
+ p.sceneRect = QRect(0, 0, q->width(), q->height());
+ p.clipRect = p.sceneRect;
+ p.opacity = 1;
+ p.forceParamRefresh = false;
+ if (!isSetup) {
+ unsigned int zero = 0;
+ root->d_func()->setupPainting(0, QRect(), &zero);
+ }
+ root->d_func()->paint(p);
+
+ lrpTime = lrpTimer.elapsed();
+}
+
+QSimpleCanvas::Matrix QSimpleCanvasItemPrivate::localTransform() const
+{
+ Q_Q(const QSimpleCanvasItem);
+
+ QSimpleCanvas::Matrix trans;
+ trans.translate(q->x(), q->y());
+ QPointF to = transformOrigin();
+ trans.translate(to.x(), to.y());
+ trans.scale(q->scale().value(), q->scale().value());
+ trans.translate(-to.x(), -to.y());
+ trans *= transformUser;
+ return trans;
+}
+
+void QSimpleCanvasItemPrivate::simplePaintChild(const GLPaintParameters &params, QSimpleCanvasItem *child)
+{
+ GLPaintParameters childParams = params;
+
+ if (child->d_func()->activeOpacity != 0) {
+ childParams.boundingRect = child->boundingRect();
+ child->d_func()->paint(childParams);
+ }
+}
+
+void QSimpleCanvasItemPrivate::paintChild(const GLPaintParameters &params,
+ QSimpleCanvasItem *child)
+{
+ if (params.forceParamRefresh) {
+ QSimpleCanvas::Matrix t = child->d_func()->transformActive;
+ qreal o = child->d_func()->activeOpacity;
+ setupChildState(child);
+ simplePaintChild(params, child);
+ child->d_func()->transformActive = t;
+ child->d_func()->activeOpacity = o;
+ } else {
+ simplePaintChild(params, child);
+ }
+}
+
+
+void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child)
+{
+ qreal visible = child->visible().value();
+ child->d_func()->activeOpacity = activeOpacity;
+ if (visible != 1)
+ child->d_func()->activeOpacity *= visible;
+
+ if (child->d_func()->activeOpacity != 0) {
+ // Calculate child's transform
+ qreal x = child->x();
+ qreal y = child->y();
+ qreal scale = child->scale().value();
+ QSimpleCanvasItem::Flip flip = child->flip();
+
+ QSimpleCanvas::Matrix &am = child->d_func()->transformActive;
+ am = transformActive;
+ if (x != 0 || y != 0)
+ am.translate(x, y);
+ if (scale != 1) {
+ QPointF to = child->d_func()->transformOrigin();
+ if (to.x() != 0. || to.y() != 0.)
+ am.translate(to.x(), to.y());
+ am.scale(scale, scale);
+ if (to.x() != 0. || to.y() != 0.)
+ am.translate(-to.x(), -to.y());
+ }
+ if (child->d_func()->transformUserSet)
+ am *= child->d_func()->transformUser;
+ if (flip) {
+ QRectF br = child->boundingRect();
+ am.translate(br.width() / 2., br.height() / 2);
+ am.rotate(180, (flip & QSimpleCanvasItem::VerticalFlip)?1:0, (flip & QSimpleCanvasItem::HorizontalFlip)?1:0, 0);
+ am.translate(-br.width() / 2., -br.height() / 2);
+ }
+ }
+}
+
+QRectF QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &bounding, unsigned int *zero)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ QRectF rv = transformActive.mapRect(q->boundingRect());
+
+ unsigned int oldZero = *zero;
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QSimpleCanvasItem *child = children.at(ii);
+ setupChildState(child);
+
+ if (child->d_func()->activeOpacity != 0)
+ rv |= child->d_func()->setupPainting(version, bounding, zero);
+ }
+
+ if (clip || oldZero != *zero)
+ (*zero)++;
+ transformActive.translate(0, 0, *zero);
+
+ lastPaintRect = rv;
+ return rv;
+}
+
+void QSimpleCanvasItemPrivate::paintNoClip(GLPaintParameters &params, QSimpleCanvasFilter::Layer layer)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ zOrderChildren();
+
+ int upto = 0;
+ for (upto = 0; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ if (c->zValue().value() < 0) {
+ if (layer & QSimpleCanvasFilter::ChildrenUnderItem)
+ paintChild(params, c);
+ } else {
+ break;
+ }
+ }
+
+ if (layer & QSimpleCanvasFilter::Item &&
+ q->options() & QSimpleCanvasItem::HasContents) {
+ QSimpleCanvasItem::GLPainter painter(q);
+ painter.activeTransform = transformActive;
+ painter.activeOpacity = activeOpacity;
+ painter.sceneClipRect = params.clipRect;
+
+ q->paintGLContents(painter);
+ }
+
+ if (layer & QSimpleCanvasFilter::ChildrenAboveItem) {
+ for (; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ paintChild(params, c);
+ }
+ }
+}
+
+void QSimpleCanvasItemPrivate::paint(GLPaintParameters &params, QSimpleCanvasFilter::Layer layer)
+{
+ if (!layer)
+ return;
+
+ // XXX Handle separate cliping modes
+ if (clip) {
+
+ GLSaveScissor ss;
+ qreal width = params.boundingRect.width();
+ qreal height = params.boundingRect.height();
+ float margin = width + height;
+
+ GLfloat clipvertices[] =
+ {
+ -margin, -margin,
+ margin, -margin,
+ margin, 0,
+
+ -margin, -margin,
+ -margin, 0,
+ margin, 0,
+
+ -margin, 0,
+ -margin, margin,
+ 0, 0,
+
+ 0, 0,
+ 0, margin,
+ -margin, margin,
+
+ 0, height,
+ 0, margin,
+ margin, margin,
+
+ margin, margin,
+ 0, height,
+ margin, height,
+
+ width, 0,
+ margin, 0,
+ margin, height,
+
+ margin, height,
+ width, height,
+ width, 0
+ };
+
+ QRectF r = transformActive.mapRect(params.boundingRect);
+ r.translate(1, 1);
+ float xscale = 0.5 * float(params.sceneRect.width());
+ float yscale = 0.5 * float(params.sceneRect.height());
+ r.moveTo(r.x() * xscale, r.y() * yscale);
+ r.setSize(QSizeF(r.width() * xscale, r.height() * yscale));
+
+ glEnable(GL_SCISSOR_TEST);
+ int sr_x = ::floorf(r.x());
+ int sr_y = ::floorf(r.y());
+ int sr_width = ::ceilf(r.right()) - sr_x;
+ int sr_height = ::ceilf(r.bottom()) - sr_y;
+
+ QRect sr(sr_x, sr_y, sr_width, sr_height);
+ if (ss.wasEnabled())
+ sr &= ss.rect();
+
+ glScissor(sr.x(), sr.y(), sr.width(), sr.height());
+
+ {
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(transformActive.data());
+ glDepthMask(GL_TRUE);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, clipvertices);
+ glDrawArrays(GL_TRIANGLES, 0, 24);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDepthMask(GL_FALSE);
+ }
+
+ GLPaintParameters newParams = params;
+ newParams.clipRect = sr;
+ newParams.clipRect.moveTo(sr.x(), params.sceneRect.height() - sr.y() - sr.height());
+ paintNoClip(newParams, layer);
+ } else {
+ paintNoClip(params, layer);
+ }
+}
+
+QGLShaderProgram *QSimpleCanvasItem::GLPainter::useTextureShader()
+{
+ qFatal("Cannot call QSimpleCanvasItem::GLPainter::useTextureShader() when using OpenGL ES 1.1");
+ return 0;
+}
+
+QGLShaderProgram *QSimpleCanvasItem::GLPainter::useColorShader(const QColor &color)
+{
+ Q_UNUSED(color);
+ qFatal("Cannot call QSimpleCanvasItem::GLPainter::useColorShader() when using OpenGL ES 1.1");
+ return 0;
+}
+
+GLBasicShaders *QSimpleCanvasItemPrivate::basicShaders() const
+{
+ qFatal("Cannot call QSimpleCanvasItem::basicShaders() when using OpenGL ES 1.1");
+ return 0;
+}
+
+QGLFramebufferObject *QSimpleCanvasPrivate::acquire(int, int)
+{
+ return 0;
+}
+
+void QSimpleCanvasPrivate::release(QGLFramebufferObject *)
+{
+}
+
+void QSimpleCanvasItem::GLPainter::drawImage(const QPointF &point,
+ const GLTexture &texture)
+{
+ drawImage(QRectF(point, QSizeF(texture.width(), texture.height())), texture);
+}
+
+void QSimpleCanvasItem::GLPainter::drawImage(const QRectF &rect,
+ const GLTexture &img)
+{
+ qFatal("Cannot call QSimpleCanvasItem::GLPainter::drawImage() when using OpenGL ES 1.1");
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas_p.h b/src/declarative/canvas/qsimplecanvas_p.h
new file mode 100644
index 0000000..7bc7330
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_p.h
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVAS_P_H
+#define QSIMPLECANVAS_P_H
+
+#include "qsimplecanvas.h"
+#include <qstack.h>
+#include <qdatetime.h>
+
+#if defined(QFX_RENDER_OPENGL)
+
+#if defined(QFX_RENDER_OPENGL2)
+#include "glbasicshaders.h"
+#endif
+
+#include <QGLWidget>
+QT_BEGIN_NAMESPACE
+
+class CanvasEGLWidget : public QGLWidget
+{
+public:
+ CanvasEGLWidget(QSimpleCanvas *parent, QSimpleCanvasPrivate *canvas)
+ :
+ QGLWidget(parent),
+ _canvas(canvas)
+ {
+ }
+
+ virtual void paintGL();
+ virtual void resizeGL(int,int);
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void initializeGL();
+
+ void updateGL();
+ void updateGL(const QRect &);
+
+ QRect map(const QRectF &) const;
+private:
+ QRect _clip;
+ QSimpleCanvasPrivate *_canvas;
+ QSimpleCanvas::Matrix defaultTransform;
+ QSimpleCanvas::Matrix invDefaultTransform;
+};
+#endif
+
+#include <QGraphicsView>
+#include <QGraphicsScene>
+
+struct QSimpleCanvasGraphicsView : public QGraphicsView
+{
+public:
+ QSimpleCanvasGraphicsView(QSimpleCanvasPrivate *parent);
+ ~QSimpleCanvasGraphicsView();
+
+protected:
+ virtual void paintEvent(QPaintEvent *);
+ virtual void focusInEvent(QFocusEvent *);
+
+private:
+ QSimpleCanvasPrivate *canvas;
+ QGraphicsScene _scene;
+};
+
+class QGLFramebufferObject;
+class QSimpleCanvasServer;
+class QSimpleCanvasPrivate
+{
+public:
+ QSimpleCanvasPrivate(QSimpleCanvas *canvas)
+ : q(canvas), timer(0), root(0), lrpTime(0), canvasServer(0), focusItem(0),
+ lastFocusItem(0), lastMouseItem(0),
+ isSetup(false), view(0)
+#if defined(QFX_RENDER_OPENGL)
+ ,egl(q, this), basicShadersInstance(0)
+#endif
+ {
+ }
+
+ QSimpleCanvas *q;
+ QSimpleCanvas::CanvasMode mode;
+ bool isSimpleCanvas() const { return mode == QSimpleCanvas::SimpleCanvas; }
+ bool isGraphicsView() const { return mode == QSimpleCanvas::GraphicsView; }
+
+#if defined(QFX_RENDER_OPENGL)
+ QRectF oldDirty;
+#else
+ QRect oldDirty;
+#endif
+ QRegion resetDirty();
+ void paint(QPainter &p);
+
+
+ int timer;
+
+ QSimpleCanvasLayer *root;
+ QList<QSimpleCanvasItem *> dirtyItems;
+ int lrpTime;
+
+ QTime frameTimer;
+ QTime lrpTimer;
+
+ QSimpleCanvasServer *canvasServer;
+
+ QStack<QSimpleCanvasItem *> focusPanels;
+ QHash<QSimpleCanvasItem *, QSimpleCanvasItem *> focusPanelData;
+ QSimpleCanvasItem *focusItem;
+ QSimpleCanvasItem *lastFocusItem;
+
+ QRect dirtyItemClip() const;
+ void clearFocusPanel(QSimpleCanvasItem *);
+ void setActiveFocusPanel(QSimpleCanvasItem *, Qt::FocusReason focusReason = Qt::OtherFocusReason);
+ void switchToFocusPanel(QSimpleCanvasItem *, QSimpleCanvasItem *, Qt::FocusReason focusReason);
+
+ void setFocusItem(QSimpleCanvasItem *item, Qt::FocusReason focusReason,
+ bool overwrite = true);
+ void clearFocusItem(QSimpleCanvasItem *item);
+
+ void clearActiveFocusItem(QSimpleCanvasItem *, Qt::FocusReason focusReason);
+ void setActiveFocusItem(QSimpleCanvasItem *, Qt::FocusReason focusReason);
+ void installMouseFilter(QSimpleCanvasItem *);
+ void removeMouseFilter(QSimpleCanvasItem *);
+ QList<QSimpleCanvasItem *> mouseFilters;
+ bool filter(QMouseEvent *e);
+ bool deliverMousePress(QSimpleCanvasItem *, QMouseEvent *, bool = false);
+ QGraphicsSceneMouseEvent *mouseEventToSceneMouseEvent(QMouseEvent *, const QPoint &);
+ QSimpleCanvasItem *lastMouseItem;
+ void sendMouseEvent(QSimpleCanvasItem *, QGraphicsSceneMouseEvent *);
+
+ bool isSetup;
+
+ void init(QSimpleCanvas::CanvasMode mode);
+
+ QSimpleCanvasGraphicsView *view;
+
+#if defined(QFX_RENDER_OPENGL)
+ CanvasEGLWidget egl;
+ GLBasicShaders *basicShaders() const
+ {
+#if defined(QFX_RENDER_OPENGL2)
+ if (!basicShadersInstance)
+ basicShadersInstance = new GLBasicShaders;
+ return basicShadersInstance;
+#else
+ return 0;
+#endif
+ }
+ mutable GLBasicShaders *basicShadersInstance;
+
+ QList<QGLFramebufferObject *> frameBuffers;
+ QGLFramebufferObject *acquire(int, int);
+ void release(QGLFramebufferObject *);
+ void paintGL();
+#endif
+};
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas_software.cpp b/src/declarative/canvas/qsimplecanvas_software.cpp
new file mode 100644
index 0000000..194024d
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_software.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvas.h"
+#include "qsimplecanvasitem_p.h"
+
+
+QT_BEGIN_NAMESPACE
+QRect QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &bounding)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ QRectF boundingRectActive = q->boundingRect();
+ QRect rv =
+ data()->transformActive.mapRect(boundingRectActive).toAlignedRect() & bounding;
+ QRect myBounding = bounding;
+ if (q->clip())
+ myBounding &= rv;
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QSimpleCanvasItem *child = children.at(ii);
+
+ qreal visible = child->visible();
+ child->d_func()->data()->activeOpacity = data()->activeOpacity;
+ if (visible != 1)
+ child->d_func()->data()->activeOpacity *= visible;
+
+ if (child->d_func()->data()->activeOpacity != 0) {
+ // Calculate child's transform
+ qreal x = child->x();
+ qreal y = child->y();
+ qreal scale = child->scale();
+ QSimpleCanvasItem::Flip flip = child->flip();
+
+ QSimpleCanvas::Matrix &am = child->d_func()->data()->transformActive;
+ am = data()->transformActive;
+ if (x != 0 || y != 0)
+ am.translate(x, y);
+ if (scale != 1) {
+ QPointF to = child->d_func()->transformOrigin();
+ if (to.x() != 0. || to.y() != 0.)
+ am.translate(to.x(), to.y());
+ am.scale(scale, scale);
+ if (to.x() != 0. || to.y() != 0.)
+ am.translate(-to.x(), -to.y());
+ }
+
+ if (child->d_func()->data()->transformUser)
+ am = *child->d_func()->data()->transformUser * am;
+
+ if (flip) {
+ QRectF br = child->boundingRect();
+ am.translate(br.width() / 2., br.height() / 2);
+ am.scale((flip & QSimpleCanvasItem::HorizontalFlip)?-1:1,
+ (flip & QSimpleCanvasItem::VerticalFlip)?-1:1);
+ am.translate(-br.width() / 2., -br.height() / 2);
+ }
+ child->d_func()->data()->transformValid = true;
+ rv |= child->d_func()->setupPainting(version, myBounding);
+ }
+ }
+
+ data()->lastPaintRect = rv;
+ return rv;
+}
+
+void QSimpleCanvasItemPrivate::paint(QPainter &p)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ QRect oldUcr;
+ if (clip) {
+
+ p.save();
+ QRectF boundingRectActive = q->boundingRect();
+
+ QRect cr;
+ switch(clip) {
+ case QSimpleCanvasItem::ClipToHeight:
+ {
+ qWarning("QSimpleCanvasItem: ClipToHeight not implemented");
+ QRect r = p.clipRegion().boundingRect();
+ cr = QRect(r.x(), 0, r.width(),
+ boundingRectActive.height());
+ }
+ break;
+ case QSimpleCanvasItem::ClipToWidth:
+ {
+ qWarning("QSimpleCanvasItem: ClipToWidth not implemented");
+ QRect r = p.clipRegion().boundingRect();
+ cr = QRect(0, r.y(), boundingRectActive.width(),
+ r.height());
+ }
+ break;
+ case QSimpleCanvasItem::ClipToRect:
+ cr = boundingRectActive.toAlignedRect();
+ break;
+ default:
+ break;
+ }
+
+ p.setWorldTransform(data()->transformActive);
+ if (p.clipRegion().isEmpty()) {
+ p.setClipRect(cr);
+ } else {
+ p.setClipRect(cr, Qt::IntersectClip);
+ }
+
+ if (p.clipRegion().isEmpty()) {
+ p.restore();
+ return;
+ }
+ }
+
+ zOrderChildren();
+
+ int upto = 0;
+ for (upto = 0; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ if (c->z() < 0) {
+ paintChild(p, c);
+ } else {
+ break;
+ }
+ }
+
+ p.setWorldTransform(data()->transformActive);
+ q->paintContents(p);
+
+ for (; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ paintChild(p, c);
+ }
+
+ if (clip)
+ p.restore();
+
+ if (debuggerStatus && debuggerStatus->selected) {
+ p.setWorldTransform(data()->transformActive);
+ p.fillRect(q->boundingRect(), QColor(255, 0, 0, 80));
+ }
+}
+
+void QSimpleCanvasItemPrivate::paintChild(QPainter &p, QSimpleCanvasItem *c)
+{
+ if (c->d_func()->data()->activeOpacity != 0) {
+
+ qreal op = p.opacity();
+ p.setOpacity(c->d_func()->data()->activeOpacity);
+
+ c->d_func()->paint(p);
+
+ p.setOpacity(op);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasfilter.cpp b/src/declarative/canvas/qsimplecanvasfilter.cpp
new file mode 100644
index 0000000..5bc6b35
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasfilter.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvasfilter.h"
+#include "qsimplecanvasfilter_p.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvas.h"
+#include "qsimplecanvas_p.h"
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glsave.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass Filter
+ \brief A Filter is a graphical filter that can be applied to items.
+*/
+
+QSimpleCanvasFilter::QSimpleCanvasFilter(QObject *parent)
+: QObject(parent), d(new QSimpleCanvasFilterPrivate(this))
+{
+}
+
+QSimpleCanvasFilter::~QSimpleCanvasFilter()
+{
+ if (d->item) d->item->setFilter(0);
+ delete d; d = 0;
+}
+
+bool QSimpleCanvasFilter::enabled() const
+{
+ return d->enabled;
+}
+
+/*!
+ \qmlproperty bool Filter::enabled
+ \brief Controls whether the filter is applied.
+*/
+
+void QSimpleCanvasFilter::setEnabled(bool e)
+{
+ if (e == d->enabled)
+ return;
+ d->enabled = e;
+ emit enabledChanged();
+ update();
+}
+
+QGLFramebufferObject *QSimpleCanvasFilter::renderToFBO(float scale, const QRectF &src, const QPoint &offset, Layer)
+{
+ // XXX - respect src
+#if defined(QFX_RENDER_OPENGL2)
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+
+ QSimpleCanvasItem *item = d->item;
+ QRect br = item->itemBoundingRect();
+ if (br.isEmpty())
+ return 0;
+ QGLFramebufferObject *fbo =
+ item->canvas()->d->acquire(int(br.width() * scale), int(br.height() * scale));
+
+ GLSaveViewport sv; GLSaveScissor ss;
+ qreal oldOpacity = item->d_func()->data()->activeOpacity;
+ item->d_func()->data()->activeOpacity = 1;
+
+ fbo->bind();
+
+ glClearColor(0,0,0,0);
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(0, 0, int(br.width() * scale), int(br.height() * scale));
+ glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, int(br.width() * scale), int(br.height() * scale));
+
+ QMatrix4x4 mat;
+ mat.flipCoordinates();
+ mat.translate(-1, -1, 0);
+ mat.scale(2. / (br.width()), 2. / (br.height()), 1. / (1024. * 1024.));
+
+ renderToScreen(mat);
+
+ fbo->release();
+
+ item->d_func()->data()->activeOpacity = oldOpacity;
+ return fbo;
+#else
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+ Q_UNUSED(scale);
+ return 0;
+#endif
+}
+
+QGLFramebufferObject *QSimpleCanvasFilter::renderToFBO(const QRectF &src, const QPoint &offset, Layer)
+{
+ // XXX - respect src
+#if defined(QFX_RENDER_OPENGL2)
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+
+ QSimpleCanvasItem *item = d->item;
+ QRect br = item->itemBoundingRect();
+ if (br.isEmpty())
+ return 0;
+ QGLFramebufferObject *fbo =
+ item->canvas()->d->acquire(br.width(), br.height());
+
+ GLSaveViewport sv; GLSaveScissor ss;
+ qreal oldOpacity = item->d_func()->data()->activeOpacity;
+ item->d_func()->data()->activeOpacity = 1;
+
+ fbo->bind();
+
+ glClearColor(0,0,0,0);
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(0, 0, br.width(), br.height());
+ glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, br.width(), br.height());
+
+ QMatrix4x4 mat;
+ mat.flipCoordinates();
+ mat.translate(-1, -1, 0);
+ mat.scale(2. / br.width(), 2. / br.height(), 1. / (1024. * 1024.));
+
+ renderToScreen(mat);
+
+ fbo->release();
+
+ item->d_func()->data()->activeOpacity = oldOpacity;
+ return fbo;
+#else
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+ return 0;
+#endif
+}
+
+QGLFramebufferObject *QSimpleCanvasFilter::acquireFBO(const QSize &s)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ QSize size;
+ QSimpleCanvasItem *item = d->item;
+ if (size.isNull()) {
+ QRect br = item->itemBoundingRect();
+ size = br.size();
+ } else {
+ size = s;
+ }
+
+ QGLFramebufferObject *fbo =
+ item->canvas()->d->acquire(s.width(), s.height());
+
+ return fbo;
+#else
+ Q_UNUSED(s);
+ return 0;
+#endif
+}
+
+void QSimpleCanvasFilter::releaseFBO(QGLFramebufferObject *fbo)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ d->item->d_func()->canvas->d->release(fbo);
+#else
+ Q_UNUSED(fbo);
+#endif
+}
+
+void QSimpleCanvasFilter::renderToScreen(const QRectF &src, Layer layer)
+{
+ // XXX - respect src
+#if defined(QFX_RENDER_OPENGL2)
+ Q_UNUSED(src);
+ Q_UNUSED(layer);
+ d->item->d_func()->paint(d->params, layer);
+#else
+ Q_UNUSED(src);
+ Q_UNUSED(layer);
+#endif
+}
+
+void QSimpleCanvasFilter::renderToScreen(const QSimpleCanvas::Matrix &trans, const QRectF &src, Layer layer)
+{
+ // XXX - respect src
+#if defined(QFX_RENDER_OPENGL2)
+ Q_UNUSED(src);
+ QSimpleCanvas::Matrix old = d->item->d_func()->data()->transformActive;
+ d->item->d_func()->data()->transformActive = trans;
+ QSimpleCanvasItemPrivate::GLPaintParameters params = d->params;
+ params.forceParamRefresh = true;
+ d->item->d_func()->paint(params, layer);
+ d->item->d_func()->data()->transformActive = old;
+#else
+ Q_UNUSED(trans);
+ Q_UNUSED(src);
+ Q_UNUSED(layer);
+#endif
+}
+
+QSimpleCanvasItem *QSimpleCanvasFilter::item() const
+{
+ return d->item;
+}
+
+void QSimpleCanvasFilter::setItem(QSimpleCanvasItem *i)
+{
+ if (d->item == i)
+ return;
+ if (d->item) {
+ d->item->setFilter(0);
+ d->item = 0;
+ }
+
+ if (i->filter() != this) {
+ i->setFilter(this);
+ } else {
+ d->item = i;
+ }
+}
+
+#if defined(QFX_RENDER_OPENGL2)
+void QSimpleCanvasFilterPrivate::doFilterGL(QSimpleCanvasItem::GLPainter &p, const QSimpleCanvasItemPrivate::GLPaintParameters &prms)
+{
+ params = prms;
+ q->filterGL(p);
+}
+#endif
+
+QRectF QSimpleCanvasFilter::itemBoundingRect(const QRectF &r) const
+{
+ return r;
+}
+
+void QSimpleCanvasFilter::filterGL(QSimpleCanvasItem::GLPainter &p)
+{
+ Q_UNUSED(p);
+}
+
+void QSimpleCanvasFilter::filter(QPainter &)
+{
+}
+
+void QSimpleCanvasFilter::update()
+{
+ if (d->item)
+ d->item->update();
+}
+
+#if defined(QFX_RENDER_OPENGL2)
+bool QSimpleCanvasFilterPrivate::isSimpleItem(QSimpleCanvasItem *item, QSimpleCanvasItem **out, QSimpleCanvas::Matrix *mout)
+{
+ if (item->options() & QSimpleCanvasItem::SimpleItem && !item->hasChildren()) {
+ *out = item;
+ return true;
+ } else if (!(item->options() & QSimpleCanvasItem::HasContents) &&
+ item->children().count() == 1) {
+ QSimpleCanvasItem *child = item->children().first();
+ if (child->filter() && child->filter()->enabled())
+ return false;
+ bool rv = isSimpleItem(child, out, mout);
+ if (rv)
+ *mout *= child->d_func()->localTransform();
+ return rv;
+ } else {
+ return false;
+ }
+}
+#endif
+
+bool QSimpleCanvasFilter::isSimpleItem(QSimpleCanvasItem **out, QSimpleCanvas::Matrix *mout)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ return d->isSimpleItem(item(), out, mout);
+#else
+ Q_UNUSED(out);
+ Q_UNUSED(mout);
+#endif
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasfilter.h b/src/declarative/canvas/qsimplecanvasfilter.h
new file mode 100644
index 0000000..cb75ddf
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasfilter.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVASFILTER_H
+#define QSIMPLECANVASFILTER_H
+
+#include <QtCore/qobject.h>
+#include <qfxglobal.h>
+#include <qsimplecanvasitem.h>
+#include <qsimplecanvas.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QSimpleCanvasFilterPrivate;
+class QRectF;
+class QPoint;
+class QGLFramebufferObject;
+class GLShaderProgram;
+class Q_DECLARATIVE_EXPORT QSimpleCanvasFilter : public QObject
+{
+Q_OBJECT
+public:
+ QSimpleCanvasFilter(QObject *parent);
+ virtual ~QSimpleCanvasFilter();
+
+ enum Layer { ChildrenUnderItem = 0x01,
+ Item = 0x02,
+ ChildrenAboveItem = 0x04,
+ All = 0x07 };
+
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged);
+ bool enabled() const;
+ void setEnabled(bool);
+
+ QSimpleCanvasItem *item() const;
+ void setItem(QSimpleCanvasItem *);
+Q_SIGNALS:
+ void enabledChanged();
+
+protected:
+
+ virtual QRectF itemBoundingRect(const QRectF &) const;
+ virtual void filterGL(QSimpleCanvasItem::GLPainter &p);
+ virtual void filter(QPainter &p);
+
+ QGLFramebufferObject *renderToFBO(const QRectF &src = QRect(), const QPoint &offset = QPoint(), Layer = All);
+ QGLFramebufferObject *renderToFBO(float scale, const QRectF &src = QRect(), const QPoint &offset = QPoint(), Layer = All);
+ QGLFramebufferObject *acquireFBO(const QSize & = QSize());
+ void releaseFBO(QGLFramebufferObject *);
+
+ void renderToScreen(const QRectF &src = QRect(), Layer = All);
+ void renderToScreen(const QSimpleCanvas::Matrix &trans, const QRectF &src = QRect(), Layer = All);
+
+ void update();
+
+ bool isSimpleItem(QSimpleCanvasItem **, QSimpleCanvas::Matrix *);
+
+private:
+ friend class QSimpleCanvasFilterPrivate;
+ friend class QSimpleCanvasItemPrivate;
+ friend class QSimpleCanvasItem;
+
+ QSimpleCanvasFilterPrivate *d;
+};
+
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/canvas/qsimplecanvasfilter_p.h b/src/declarative/canvas/qsimplecanvasfilter_p.h
new file mode 100644
index 0000000..1c72993
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasfilter_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVASFILTER_P_H
+#define QSIMPLECANVASFILTER_P_H
+
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvasitem_p.h"
+
+
+QT_BEGIN_NAMESPACE
+class QSimpleCanvasFilterPrivate
+{
+public:
+ QSimpleCanvasFilterPrivate(QSimpleCanvasFilter *_q)
+ : q(_q), item(0), enabled(true) {}
+
+ QSimpleCanvasFilter *q;
+
+ QSimpleCanvasItem *item;
+ bool enabled;
+#if defined(QFX_RENDER_OPENGL)
+ QSimpleCanvasItemPrivate::GLPaintParameters params;
+
+ void doFilterGL(QSimpleCanvasItem::GLPainter &, const QSimpleCanvasItemPrivate::GLPaintParameters &);
+
+ bool isSimpleItem(QSimpleCanvasItem *item, QSimpleCanvasItem **out, QSimpleCanvas::Matrix *mout);
+#endif
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/canvas/qsimplecanvasitem.cpp b/src/declarative/canvas/qsimplecanvasitem.cpp
new file mode 100644
index 0000000..12c725c
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasitem.cpp
@@ -0,0 +1,1868 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvas.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvas_p.h"
+#include <qfxitem.h>
+#include <QGraphicsSceneEvent>
+
+
+QT_BEGIN_NAMESPACE
+QSimpleCanvasItemData::QSimpleCanvasItemData()
+: buttons(Qt::NoButton), flip(QSimpleCanvasItem::NoFlip),
+ dirty(false), transformValid(true), x(0), y(0), z(0), visible(1),
+ transformUser(0), activeOpacity(1)
+{
+}
+
+QSimpleCanvasItemData::~QSimpleCanvasItemData()
+{
+ if (transformUser)
+ delete transformUser;
+}
+
+/*!
+ \internal
+ \class QSimpleCanvasItem
+ \brief The QSimpleCanvasItem class is the base class of canvas items.
+ */
+QSimpleCanvasLayer::QSimpleCanvasLayer()
+{
+}
+
+QSimpleCanvasLayer::QSimpleCanvasLayer(QSimpleCanvasItem *parent)
+: QSimpleCanvasItem(parent)
+{
+}
+
+void QSimpleCanvasLayer::addChild(QSimpleCanvasItem *c)
+{
+ QSimpleCanvasItem::addChild(c);
+}
+
+void QSimpleCanvasLayer::addDirty(QSimpleCanvasItem *)
+{
+}
+
+void QSimpleCanvasLayer::remDirty(QSimpleCanvasItem *)
+{
+}
+
+QSimpleCanvasLayer *QSimpleCanvasLayer::layer()
+{
+ return this;
+}
+
+QSimpleCanvasItem::Options QSimpleCanvasItem::options() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return (QSimpleCanvasItem::Options)d->options;
+}
+
+bool QSimpleCanvasItem::mouseFilter(QGraphicsSceneMouseEvent *)
+{
+ return false;
+}
+
+void QSimpleCanvasItem::mousePressEvent(QGraphicsSceneMouseEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::hoverEnterEvent(QGraphicsSceneHoverEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::mouseUngrabEvent()
+{
+}
+
+void QSimpleCanvasItem::keyPressEvent(QKeyEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::keyReleaseEvent(QKeyEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::focusOutEvent(QFocusEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::focusInEvent(QFocusEvent *e)
+{
+ e->ignore();
+}
+
+void QSimpleCanvasItem::activePanelInEvent()
+{
+}
+
+void QSimpleCanvasItem::activePanelOutEvent()
+{
+}
+
+void QSimpleCanvasItem::inputMethodEvent(QInputMethodEvent *e)
+{
+ e->ignore();
+}
+
+QVariant QSimpleCanvasItem::inputMethodQuery(Qt::InputMethodQuery) const
+{
+ return QVariant();
+}
+
+void QSimpleCanvasItem::childrenChanged()
+{
+}
+
+QRectF QSimpleCanvasItem::boundingRect() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return QRectF(0., 0., d->width, d->height);
+}
+
+void QSimpleCanvasItem::paintContents(QPainter &)
+{
+}
+
+void QSimpleCanvasItem::paintGLContents(GLPainter &)
+{
+}
+
+uint QSimpleCanvasItem::glSimpleItemData(float *vertices, float *texVertices,
+ GLTexture **texture, uint count)
+{
+ Q_UNUSED(vertices);
+ Q_UNUSED(texVertices);
+ Q_UNUSED(texture);
+ Q_UNUSED(count);
+ return 0;
+}
+
+void QSimpleCanvasItem::canvasChanged()
+{
+}
+
+void QSimpleCanvasItem::focusChanged(bool)
+{
+}
+
+void QSimpleCanvasItem::activeFocusChanged(bool)
+{
+}
+
+void QSimpleCanvasItem::parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *)
+{
+}
+
+GLBasicShaders *QSimpleCanvasItem::basicShaders() const
+{
+#if defined(QFX_RENDER_OPENGL2)
+ return canvas()->d->basicShaders();
+#else
+ return 0;
+#endif
+}
+
+/*!
+ Returns the item's (0, 0) point relative to its parent.
+ */
+QPointF QSimpleCanvasItem::pos() const
+{
+ return QPointF(x(),y());
+}
+
+/*!
+ Returns the item's (0, 0) point mapped to scene coordinates.
+ */
+QPointF QSimpleCanvasItem::scenePos() const
+{
+ return mapToScene(QPointF(0, 0));
+}
+
+/*!
+ \enum QSimpleCanvasItem::TransformOrigin
+
+ Controls the point about which simple transforms like scale apply.
+
+ \value TopLeft The top-left corner of the item.
+ \value TopCenter The center point of the top of the item.
+ \value TopRight The top-right corner of the item.
+ \value MiddleLeft The left most point of the vertical middle.
+ \value Center The center of the item.
+ \value MiddleRight The right most point of the vertical middle.
+ \value BottomLeft The bottom-left corner of the item.
+ \value BottomCenter The center point of the bottom of the item.
+ \value BottomRight The bottom-right corner of the item.
+*/
+
+/*!
+ Returns the current transform origin.
+*/
+QSimpleCanvasItem::TransformOrigin QSimpleCanvasItem::transformOrigin() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->origin;
+}
+
+/*!
+ Set the transform \a origin.
+*/
+void QSimpleCanvasItem::setTransformOrigin(TransformOrigin origin)
+{
+ Q_D(QSimpleCanvasItem);
+ if (origin != d->origin) {
+ d->origin = origin;
+ update();
+ }
+}
+
+QPointF QSimpleCanvasItem::transformOriginPoint() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->transformOrigin();
+}
+
+/*!
+ Returns the canvas the item is on, or 0 if the item is not on a canvas.
+ */
+QSimpleCanvas *QSimpleCanvasItem::canvas() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->canvas;
+}
+
+/*!
+ Returns the parent if the item, or 0 if the item has no parent.
+ */
+QSimpleCanvasItem *QSimpleCanvasItem::parent() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->parent;
+}
+
+void QSimpleCanvasItemPrivate::zOrderChildren()
+{
+ if (!needsZOrder || children.count() <= 1)
+ return;
+
+ needsZOrder = false;
+ // This is a bubble sort for a reason - it is the fastest sort for a mostly
+ // ordered list. We only expect z ordering to change infrequently.
+ bool swap = true;
+ int c = 0;
+ while(swap) {
+ ++c;
+ swap = false;
+ QSimpleCanvasItem *item = children.first();
+ qreal z = item->z();
+ for (int ii = 1; ii < children.count(); ++ii) {
+ QSimpleCanvasItem *i2 = children.at(ii);
+ qreal z2 = i2->z();
+ if (z2 < z) {
+ swap = true;
+ children[ii] = item;
+ children[ii - 1] = i2;
+ } else {
+ item = i2;
+ z = z2;
+ }
+ }
+ }
+}
+
+void QSimpleCanvasItemPrivate::canvasChanged(QSimpleCanvas *newCanvas, QSimpleCanvas *oldCanvas)
+{
+ Q_Q(QSimpleCanvasItem);
+ canvas = newCanvas;
+ if (options & QSimpleCanvasItem::MouseFilter) {
+ if (oldCanvas) oldCanvas->d->removeMouseFilter(q);
+ if (newCanvas) newCanvas->d->installMouseFilter(q);
+ }
+ if (newCanvas) {
+ if (!oldCanvas && hasFocus)
+ newCanvas->d->setFocusItem(q, Qt::OtherFocusReason, false);
+ if (wantsActiveFocusPanelPendingCanvas) {
+ hasBeenActiveFocusPanel = true;
+ newCanvas->d->setActiveFocusPanel(q);
+ wantsActiveFocusPanelPendingCanvas = false;
+ }
+ }
+
+ for (int ii = 0; ii < children.count(); ++ii)
+ children.at(ii)->d_func()->canvasChanged(newCanvas, oldCanvas);
+ q->canvasChanged();
+}
+
+void QSimpleCanvasItem::setFocus(bool focus)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->hasFocus == focus)
+ return;
+ QSimpleCanvas *c = canvas();
+
+ if (c) {
+ if (focus)
+ c->d->setFocusItem(this, Qt::OtherFocusReason);
+ else
+ c->d->clearFocusItem(this);
+ } else {
+ d->setFocus(focus);
+ focusChanged(d->hasFocus);
+ }
+}
+
+qreal QSimpleCanvasItem::x() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return d->graphicsItem->x();
+ else if (d->data_ptr)
+ return d->data()->x;
+ else
+ return 0;
+}
+
+qreal QSimpleCanvasItem::y() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return d->graphicsItem->y();
+ else if (d->data_ptr)
+ return d->data()->y;
+ else
+ return 0;
+}
+
+qreal QSimpleCanvasItem::z() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return d->graphicsItem->zValue();
+ else if (d->data_ptr)
+ return d->data()->z;
+ else
+ return 0;
+}
+
+void QSimpleCanvasItem::setX(qreal x)
+{
+ Q_D(QSimpleCanvasItem);
+ if (x == this->x())
+ return;
+
+ qreal oldX = this->x();
+
+ if (d->graphicsItem) {
+ d->graphicsItem->setPos(x, y());
+ } else {
+ d->data()->x = x;
+ update();
+ }
+
+ geometryChanged(QRectF(this->x(), y(), width(), height()),
+ QRectF(oldX, y(), width(), height()));
+}
+
+void QSimpleCanvasItem::setY(qreal y)
+{
+ Q_D(QSimpleCanvasItem);
+ if (y == this->y())
+ return;
+
+ qreal oldY = this->y();
+
+ if (d->graphicsItem) {
+ d->graphicsItem->setPos(x(), y);
+ } else {
+ d->data()->y = y;
+ update();
+ }
+
+ geometryChanged(QRectF(x(), this->y(), width(), height()),
+ QRectF(x(), oldY, width(), height()));
+}
+
+void QSimpleCanvasItem::setZ(qreal z)
+{
+ Q_D(QSimpleCanvasItem);
+ if (z == this->z())
+ return;
+
+ if (d->graphicsItem) {
+
+ if (z < 0)
+ d->graphicsItem->setFlag(QGraphicsItem::ItemStacksBehindParent,
+ true);
+ else
+ d->graphicsItem->setFlag(QGraphicsItem::ItemStacksBehindParent,
+ false);
+
+ d->graphicsItem->setZValue(z);
+
+ } else {
+ if (d->data()->z == z)
+ return;
+
+ d->data()->z = z;
+ if (parent())
+ static_cast<QSimpleCanvasItemPrivate*>(parent()->d_ptr)->needsZOrder = true;
+ update();
+ }
+}
+
+qreal QSimpleCanvasItem::width() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->width;
+}
+
+void QSimpleCanvasItem::setWidth(qreal w)
+{
+ Q_D(QSimpleCanvasItem);
+ d->widthValid = true;
+ if (d->width == w)
+ return;
+
+ qreal oldWidth = d->width;
+
+ d->width = w;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, height()));
+}
+
+void QSimpleCanvasItem::setImplicitWidth(qreal w)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->width == w || widthValid())
+ return;
+
+ qreal oldWidth = d->width;
+
+ d->width = w;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, height()));
+}
+
+bool QSimpleCanvasItem::widthValid() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->widthValid;
+}
+
+qreal QSimpleCanvasItem::height() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->height;
+}
+
+void QSimpleCanvasItem::setHeight(qreal h)
+{
+ Q_D(QSimpleCanvasItem);
+ d->heightValid = true;
+ if (d->height == h)
+ return;
+
+ qreal oldHeight = d->height;
+
+ d->height = h;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), width(), oldHeight));
+}
+
+void QSimpleCanvasItem::setImplicitHeight(qreal h)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->height == h || heightValid())
+ return;
+
+ qreal oldHeight = d->height;
+
+ d->height = h;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), width(), oldHeight));
+}
+
+bool QSimpleCanvasItem::heightValid() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->heightValid;
+}
+
+void QSimpleCanvasItem::setPos(const QPointF &point)
+{
+ Q_D(QSimpleCanvasItem);
+ qreal oldX = x();
+ qreal oldY = y();
+
+ if (d->graphicsItem) {
+ d->graphicsItem->setPos(point);
+ } else {
+ d->data()->x = point.x();
+ d->data()->y = point.y();
+ update();
+ }
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(oldX, oldY, width(), height()));
+}
+
+qreal QSimpleCanvasItem::scale() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->scale;
+}
+
+void QSimpleCanvasItem::setScale(qreal s)
+{
+ Q_D(QSimpleCanvasItem);
+ d->scale = s;
+ if (d->graphicsItem) {
+ QTransform t;
+ QPointF to = transformOriginPoint();
+ if (to.x() != 0. || to.y() != 0.)
+ t.translate(to.x(), to.y());
+ t.scale(s, s);
+ if (to.x() != 0. || to.y() != 0.)
+ t.translate(-to.x(), -to.y());
+ d->graphicsItem->setTransform(t * d->graphicsItem->transform);
+ } else {
+ update();
+ }
+}
+
+bool QSimpleCanvasItem::isVisible() const
+{
+ if (visible() <= 0)
+ return false;
+ else if (!parent())
+ return true;
+ else
+ return parent()->isVisible();
+}
+
+qreal QSimpleCanvasItem::visible() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return d->graphicsItem->opacity();
+ else if (d->data_ptr)
+ return d->data()->visible;
+ else
+ return 1;
+}
+
+void QSimpleCanvasItem::setVisible(qreal v)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ d->graphicsItem->setOpacity(v);
+ } else {
+ if (v == visible())
+ return;
+ if (v == 0)
+ update();
+
+ d->data()->visible = v;
+
+ if (v != 0)
+ update();
+ }
+}
+
+void QSimpleCanvasItem::addChild(QSimpleCanvasItem *c)
+{
+ Q_D(QSimpleCanvasItem);
+ d->children.append(c);
+ if (!d->graphicsItem)
+ d->needsZOrder = true;
+ childrenChanged();
+}
+
+void QSimpleCanvasItem::remChild(QSimpleCanvasItem *c)
+{
+ Q_D(QSimpleCanvasItem);
+ d->children.removeAll(c);
+ childrenChanged();
+}
+
+QSimpleCanvasFilter *QSimpleCanvasItem::filter() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->filter;
+}
+
+/*!
+QSimpleCanvasItem takes ownership of filter.
+*/
+void QSimpleCanvasItem::setFilter(QSimpleCanvasFilter *f)
+{
+ Q_D(QSimpleCanvasItem);
+ if (!d || f == d->filter)
+ return;
+
+ d->filter = f;
+ if (d->filter)
+ d->filter->setItem(this);
+ update();
+}
+
+const QList<QSimpleCanvasItem *> &QSimpleCanvasItem::children() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->children;
+}
+
+bool QSimpleCanvasItem::hasChildren() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return !d->children.isEmpty();
+}
+
+QSimpleCanvasLayer *QSimpleCanvasItem::layer()
+{
+ if (parent())
+ return parent()->layer();
+ else
+ return 0;
+}
+
+void QSimpleCanvasItem::update()
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ d->graphicsItem->update();
+ } else {
+ if (!parent())
+ return;
+
+ if (d->data()->dirty || 0. == d->data()->visible) return;
+
+ QSimpleCanvasLayer *l = layer();
+ if (l == this && parent())
+ l = parent()->layer();
+ if (l) {
+ l->addDirty(this);
+ d->data()->dirty = true;
+ d->data()->transformValid = false;
+ }
+ }
+}
+
+bool QSimpleCanvasItem::clip() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->clip;
+}
+
+void QSimpleCanvasItem::setClip(bool c)
+{
+ Q_D(const QSimpleCanvasItem);
+ if (bool(d->clip) == c)
+ return;
+
+ if (c)
+ setClipType(ClipToRect);
+ else
+ setClipType(NoClip);
+
+ update();
+}
+
+QSimpleCanvasItem::ClipType QSimpleCanvasItem::clipType() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->clip;
+}
+
+void QSimpleCanvasItem::setClipType(ClipType c)
+{
+ Q_D(QSimpleCanvasItem);
+ d->clip = c;
+ if (d->graphicsItem)
+ d->graphicsItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape, bool(c));
+ else
+ update();
+}
+
+Qt::MouseButtons QSimpleCanvasItem::acceptedMouseButtons() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return d->graphicsItem->acceptedMouseButtons();
+ else if (d->data_ptr)
+ return (Qt::MouseButtons)d->data()->buttons;
+ else
+ return Qt::NoButton;
+}
+
+void QSimpleCanvasItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem)
+ d->graphicsItem->setAcceptedMouseButtons(buttons);
+ else
+ d->data()->buttons = buttons;
+}
+
+
+QRect QSimpleCanvasItem::itemBoundingRect()
+{
+ return boundingRect().toAlignedRect();
+}
+
+QPointF QSimpleCanvasItemPrivate::adjustFrom(const QPointF &p) const
+{
+#if defined(QFX_RENDER_OPENGL)
+ if (!canvas)
+ return p;
+
+ QPointF rv(-1. + 2. * p.x() / qreal(canvas->width()),
+ 1 - 2. * p.y() / qreal(canvas->height()));
+
+ return rv;
+#else
+ return p;
+#endif
+}
+
+QRectF QSimpleCanvasItemPrivate::adjustFrom(const QRectF &r) const
+{
+#if defined(QFX_RENDER_OPENGL)
+ if (!canvas)
+ return r;
+
+ qreal width = r.width() * 2. / qreal(canvas->width());
+ qreal height = r.height() * 2. / qreal(canvas->height());
+ qreal x = -1. + 2. * r.x() / qreal(canvas->width());
+ qreal y = 1. - 2. * r.y() / qreal(canvas->height()) - height;
+
+ return QRectF(x, y, width, height);
+#else
+ return r;
+#endif
+}
+
+QPointF QSimpleCanvasItemPrivate::adjustTo(const QPointF &p) const
+{
+#if defined(QFX_RENDER_OPENGL)
+ if (!canvas)
+ return p;
+
+ QPointF rv(0.5 * (p.x() + 1.) * qreal(canvas->width()),
+ 0.5 * (1. - p.y()) * qreal(canvas->height()));
+
+ return rv;
+#else
+ return p;
+#endif
+}
+
+QRectF QSimpleCanvasItemPrivate::adjustTo(const QRectF &r) const
+{
+#if defined(QFX_RENDER_OPENGL)
+ if (!canvas)
+ return r;
+
+ qreal width = 0.5 * r.width() * qreal(canvas->width());
+ qreal height = 0.5 * r.height() * qreal(canvas->height());
+ qreal x = 0.5 * (r.x() + 1.) * qreal(canvas->width());
+ qreal y = 0.5 * (1. - r.y()) * qreal(canvas->height()) - height;
+
+ return QRectF(x, y, width, height);
+#else
+ return r;
+#endif
+}
+
+QPointF QSimpleCanvasItem::mapFromScene(const QPointF &p) const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ return d->graphicsItem->mapFromScene(p);
+ } else {
+ QPointF mp = d->adjustFrom(p);
+ d->freshenTransforms();
+#if defined(QFX_RENDER_OPENGL)
+ // m20X + m21Y + m22Z + m23 = 1
+ // Z = (1 - m23 - m20X - m21Y) / m22
+
+ QMatrix4x4 inv = d->data()->transformActive.inverted();
+ qreal z_s = (1 - inv(2,3) - inv(2,0) * mp.x() - inv(2, 1) * mp.y()) / inv(2, 2);
+
+ QVector3D vec(mp.x(), mp.y(), z_s);
+ QVector3D r = inv.map(vec);
+
+ return r.toPointF();
+#else
+ return d->data()->transformActive.inverted().map(mp);
+#endif
+ }
+}
+
+QRectF QSimpleCanvasItem::mapFromScene(const QRectF &r) const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ return d->graphicsItem->mapFromScene(r).boundingRect();
+ } else {
+ QRectF mr = d->adjustFrom(r);
+ d->freshenTransforms();
+#if defined(QFX_RENDER_OPENGL)
+ // m20X + m21Y + m22Z + m23 = 1
+ // Z = (1 - m23 - m20X - m21Y) / m22
+
+ QMatrix4x4 inv = d->data()->transformActive.inverted();
+ qreal tl_z_s = (1 - inv(2,3) - inv(2,0) * mr.topLeft().x() - inv(2, 1) * mr.topLeft().y()) / inv(2, 2);
+ qreal tr_z_s = (1 - inv(2,3) - inv(2,0) * mr.topRight().x() - inv(2, 1) * mr.topRight().y()) / inv(2, 2);
+ qreal bl_z_s = (1 - inv(2,3) - inv(2,0) * mr.bottomLeft().x() - inv(2, 1) * mr.bottomLeft().y()) / inv(2, 2);
+ qreal br_z_s = (1 - inv(2,3) - inv(2,0) * mr.bottomRight().x() - inv(2, 1) * mr.bottomRight().y()) / inv(2, 2);
+
+ QVector3D tl(mr.topLeft().x(), mr.topLeft().y(), tl_z_s);
+ QVector3D tr(mr.topRight().x(), mr.topRight().y(), tr_z_s);
+ QVector3D bl(mr.bottomLeft().x(), mr.bottomLeft().y(), bl_z_s);
+ QVector3D br(mr.bottomRight().x(), mr.bottomRight().y(), br_z_s);
+
+ tl = inv.map(tl); tr = inv.map(tr); bl = inv.map(bl); br = inv.map(br);
+
+ qreal xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
+ qreal xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
+ qreal ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
+ qreal ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
+
+ return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
+#else
+ return d->data()->transformActive.inverted().mapRect(mr);
+#endif
+ }
+}
+
+QPointF QSimpleCanvasItem::mapToScene(const QPointF &p) const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ return d->graphicsItem->mapToScene(p);
+ } else {
+ d->freshenTransforms();
+ QPointF rp = d->data()->transformActive.map(p);
+ return d->adjustTo(rp);
+ }
+}
+
+QRectF QSimpleCanvasItem::mapToScene(const QRectF &r) const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ return d->graphicsItem->mapToScene(r).boundingRect();
+ } else {
+ d->freshenTransforms();
+ QRectF rr = d->data()->transformActive.mapRect(r);
+ return d->adjustTo(rr);
+ }
+}
+
+int QSimpleCanvasItemPrivate::nextTransformVersion = 1;
+
+void QSimpleCanvasItemPrivate::freshenTransforms() const
+{
+ if (freshenNeeded())
+ doFreshenTransforms();
+}
+
+bool QSimpleCanvasItemPrivate::freshenNeeded() const
+{
+#if 0
+ return parent &&
+ (data()->transformVersion == -1 ||
+ data()->parentTransformVersion == -1 ||
+ parent->d_func()->data()->transformVersion != data()->parentTransformVersion);
+#else
+ const QSimpleCanvasItemPrivate *me = this;
+ while(me) {
+ if (me->data_ptr && !me->data_ptr->transformValid)
+ return true;
+ if (me->parent)
+ me = me->parent->d_func();
+ else
+ me = 0;
+ }
+ return false;
+#endif
+}
+
+void QSimpleCanvasItemPrivate::doFreshenTransforms() const
+{
+ Q_Q(const QSimpleCanvasItem);
+ if (parent)
+ parent->d_func()->doFreshenTransforms();
+
+ if (freshenNeeded()) {
+ if (parent)
+ data()->transformActive = parent->d_func()->data()->transformActive;
+ else
+ data()->transformActive = QSimpleCanvas::Matrix();
+ data()->transformActive.translate(q->x(), q->y());
+ if (scale != 1.) {
+ QPointF to = transformOrigin();
+ if (to.x() != 0. || to.y() != 0.)
+ data()->transformActive.translate(to.x(), to.y());
+ data()->transformActive.scale(scale, scale);
+ if (to.x() != 0. || to.y() != 0.)
+ data()->transformActive.translate(-to.x(), -to.y());
+ }
+
+ Q_Q(const QSimpleCanvasItem);
+#if defined(QFX_RENDER_OPENGL)
+ if (q->d_func()->data()->transformUser)
+ data()->transformActive *= *q->d_func()->data()->transformUser;
+#endif
+
+ if (data()->flip) {
+ QRectF br = q->boundingRect();
+ data()->transformActive.translate(br.width() / 2., br.height() / 2);
+#if defined(QFX_RENDER_OPENGL)
+ data()->transformActive.rotate(180, (data()->flip & QSimpleCanvasItem::VerticalFlip)?1:0, (data()->flip & QSimpleCanvasItem::HorizontalFlip)?1:0, 0);
+#else
+ data()->transformActive.scale((data()->flip & QSimpleCanvasItem::HorizontalFlip)?-1:1,
+ (data()->flip & QSimpleCanvasItem::VerticalFlip)?-1:1);
+#endif
+ data()->transformActive.translate(-br.width() / 2., -br.height() / 2);
+ }
+ }
+}
+
+QSimpleCanvas::Matrix QSimpleCanvasItem::transform() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return QSimpleCanvasConfig::transformToMatrix(d->graphicsItem->transform);
+ else if (d->data()->transformUser)
+ return *d->data()->transformUser;
+ else
+ return QSimpleCanvas::Matrix();
+}
+
+void QSimpleCanvasItem::setTransform(const QSimpleCanvas::Matrix &m)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ d->graphicsItem->transform = QSimpleCanvasConfig::matrixToTransform(m);
+ d->graphicsItem->setTransform(QTransform::fromScale(d->scale, d->scale) * d->graphicsItem->transform);
+ } else {
+ if (!d->data()->transformUser)
+ d->data()->transformUser = new QSimpleCanvas::Matrix;
+ *d->data()->transformUser = m;
+ update();
+ }
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::mouseGrabberItem() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ QGraphicsScene *s = d->graphicsItem->scene();
+ if (s) {
+ QGraphicsItem *item = s->mouseGrabberItem();
+ QSimpleGraphicsItem *dgi = static_cast<QSimpleGraphicsItem *>(item);
+ return dgi?static_cast<QSimpleCanvasItem*>(dgi->owner):0;
+ }
+ } else {
+ QSimpleCanvas *c = canvas();
+ if (c)
+ return c->d->lastMouseItem;
+ }
+ return 0;
+}
+
+void QSimpleCanvasItem::ungrabMouse()
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ d->graphicsItem->ungrabMouse();
+ } else {
+ QSimpleCanvas *c = canvas();
+ if (c && c->d->lastMouseItem == this) {
+ c->d->lastMouseItem->mouseUngrabEvent();
+ c->d->lastMouseItem = 0;
+ }
+ }
+}
+
+void QSimpleCanvasItem::grabMouse()
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ d->graphicsItem->grabMouse();
+ } else {
+ QSimpleCanvas *c = canvas();
+ if (c) {
+ if (c->d->lastMouseItem != this) {
+ if (c->d->lastMouseItem)
+ c->d->lastMouseItem->mouseUngrabEvent();
+ c->d->lastMouseItem = this;
+ }
+ }
+ }
+}
+
+bool QSimpleCanvasItem::isFocusable() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->focusable;
+}
+
+void QSimpleCanvasItem::setFocusable(bool f)
+{
+ Q_D(QSimpleCanvasItem);
+ d->focusable = f;
+}
+
+bool QSimpleCanvasItem::hasFocus() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->hasFocus;
+}
+
+void QSimpleCanvasItemPrivate::setFocus(bool f)
+{
+ hasFocus = f;
+}
+
+void QSimpleCanvasItemPrivate::setActiveFocus(bool f)
+{
+ hasActiveFocus = f;
+
+ if (graphicsItem) {
+ if (f) {
+ if (!(graphicsItem->flags() & QGraphicsItem::ItemIsFocusable))
+ graphicsItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ graphicsItem->setFocus();
+ } else {
+ graphicsItem->clearFocus();
+ if ((graphicsItem->flags() & QGraphicsItem::ItemIsFocusable) && !focusable)
+ graphicsItem->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ }
+
+ }
+}
+
+QSimpleCanvasItem::Flip QSimpleCanvasItem::flip() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return NoFlip;
+ else if (d->data_ptr)
+ return d->data()->flip;
+ else
+ return NoFlip;
+}
+
+void QSimpleCanvasItem::setFlip(Flip f)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return;
+
+ if (d->data()->flip == f)
+ return;
+
+ d->data()->flip = f;
+ update();
+}
+
+/*!
+ Places the item under \a item in the parent item's stack.
+
+ The item itself and \a item must be siblings, or this method has no effect.
+
+ \sa stackOver(), stackAt()
+ */
+void QSimpleCanvasItem::stackUnder(QSimpleCanvasItem *item)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return; // XXX
+
+ QSimpleCanvasItem *p = parent();
+ if (!p || !item || item == this) return;
+
+ QSimpleCanvasItemPrivate *parent_d_ptr = static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr);
+ int idx = parent_d_ptr->children.indexOf(item);
+ if (idx == -1) return;
+
+ parent_d_ptr->children.removeAll(this);
+ idx = parent_d_ptr->children.indexOf(item);
+ parent_d_ptr->children.insert(idx + 1, this);
+ parent_d_ptr->needsZOrder = true;
+
+ p->childrenChanged();
+}
+
+/*!
+ Places the item over \a item in the parent item's stack.
+
+ The item itself and \a item must be siblings, or this method has no effect.
+
+ \sa stackUnder(), stackAt()
+ */
+void QSimpleCanvasItem::stackOver(QSimpleCanvasItem *item)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return; // XXX
+
+ QSimpleCanvasItem *p = parent();
+ if (!p || !item || item == this) return;
+
+ QSimpleCanvasItemPrivate *parent_d_ptr = static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr);
+ int idx = parent_d_ptr->children.indexOf(item);
+ if (idx == -1) return;
+
+ parent_d_ptr->children.removeAll(this);
+ idx = parent_d_ptr->children.indexOf(item);
+ parent_d_ptr->children.insert(idx, this);
+ parent_d_ptr->needsZOrder = true;
+
+ p->childrenChanged();
+}
+
+/*!
+ Places the item at position \a index in the parent item's stack.
+
+ If index is zero or less, the item is placed at the beginning of the
+ stack. If the index is greater than the number of items in the stack, the
+ item is placed at the end.
+
+ \sa stackOver(), stackUnder()
+ */
+void QSimpleCanvasItem::stackAt(int index)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem)
+ return; // XXX
+
+ QSimpleCanvasItem *p = parent();
+ if (!p) return;
+
+ QSimpleCanvasItemPrivate *parent_d_ptr = static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr);
+ parent_d_ptr->children.removeAll(this);
+
+ if (index < 0) index = 0;
+ if (index > parent_d_ptr->children.size()) index = parent_d_ptr->children.size();
+
+ parent_d_ptr->children.insert(index, this);
+ parent_d_ptr->needsZOrder = true;
+ p->childrenChanged();
+}
+
+/*!
+ Returns the current stacking index for the child \a item.
+
+ If \a item is not a child, -1 is returned.
+
+ \sa stackAt()
+ */
+int QSimpleCanvasItem::indexForChild(QSimpleCanvasItem *item)
+{
+ Q_D(QSimpleCanvasItem);
+ return d->children.indexOf(item);
+}
+
+bool QSimpleCanvasItem::eventFilter(QObject *o, QEvent *e)
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ switch(e->type()) {
+ case QEvent::GraphicsSceneMouseDoubleClick:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease:
+ if (mouseFilter(static_cast<QGraphicsSceneMouseEvent *>(e)))
+ return true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return QObject::eventFilter(o, e);
+}
+
+void QSimpleCanvasItem::setOptions(Options options, bool set)
+{
+ Q_D(QSimpleCanvasItem);
+ Options old = (Options)d->options;
+
+ if (options & IsFocusPanel) {
+ if (!set) {
+ qWarning("QSimpleCanvasItem::setOptions: Cannot unset IsFocusPanel");
+ return;
+ } else if (hasChildren()) {
+ qWarning("QSimpleCanvasItem::setOptions: Cannot set IsFocusPanel once item has children");
+ return;
+ }
+ }
+
+ if (options & IsFocusRealm) {
+ if (!set) {
+ qWarning("QSimpleCanvasItem::setOptions: Cannot unset IsFocusRealm");
+ return;
+ }
+ }
+
+ if (set)
+ d->options |= options;
+ else
+ d->options &= ~options;
+
+ if ((d->options & IsFocusPanel) && (d->options & IsFocusRealm)) {
+ qWarning("QSimpleCanvasItem::setOptions: Cannot set both IsFocusPanel and IsFocusRealm. IsFocusRealm will be unset.");
+ d->options &= ~IsFocusRealm;
+ }
+
+ if ((old & MouseFilter) != (d->options & MouseFilter)) {
+ if (d->graphicsItem) {
+ if (d->options & MouseFilter)
+ d->gvAddMouseFilter();
+ else
+ d->gvRemoveMouseFilter();
+
+ } else {
+ QSimpleCanvas *c = canvas();
+ if (c) {
+ if (d->options & MouseFilter)
+ c->d->installMouseFilter(this);
+ else
+ c->d->removeMouseFilter(this);
+ }
+ }
+ }
+}
+
+QSimpleCanvasItem::QSimpleCanvasItem(QSimpleCanvasItemPrivate &dd, QSimpleCanvasItem *parent)
+: QObject(dd, parent)
+{
+}
+
+QSimpleCanvasItem::QSimpleCanvasItem(QSimpleCanvasItem *p)
+: QObject(*(new QSimpleCanvasItemPrivate), p)
+{
+}
+
+QSimpleCanvasItem::~QSimpleCanvasItem()
+{
+ Q_D(QSimpleCanvasItem);
+ if (d->graphicsItem) {
+ if ((d->options & (IsFocusPanel|IsFocusRealm)) && d->canvas)
+ d->canvas->d->focusPanelData.remove(this);
+ if (d->hasFocus && d->canvas) {
+ QSimpleCanvasItem *prnt = parent();
+ while (prnt && !(prnt->options() & (IsFocusPanel|IsFocusRealm)))
+ prnt = prnt->parent();
+ if (prnt && d->canvas->d->focusPanelData.value(prnt) == this)
+ d->canvas->d->focusPanelData.remove(prnt);
+ }
+ if (d->filter)
+ delete d->filter;
+
+ qDeleteAll(children());
+ if (parent())
+ parent()->remChild(this);
+ delete d->graphicsItem;
+ } else {
+ update();
+ setOptions(MouseFilter, false);
+
+ if (d->canvas){
+ if (d->canvas->focusItem() == this)
+ d->canvas->d->focusItem = 0;
+ if (d->canvas->d->lastFocusItem == this)
+ d->canvas->d->lastFocusItem = 0;
+ if (d->hasBeenActiveFocusPanel)
+ d->canvas->d->clearFocusPanel(this);
+ if (d->hasFocus)
+ d->canvas->d->clearFocusItem(this);
+ }
+
+ while(!d->children.isEmpty()) {
+ QSimpleCanvasItem *child = d->children.takeFirst();
+ delete child;
+ }
+
+ delete d->filter;
+
+ if (parent() && d->data_ptr && d->data()->dirty) {
+ QSimpleCanvasLayer *l = parent()->layer();
+ if (l) {
+ l->remDirty(this);
+ }
+ }
+ if (d->parent)
+ d->parent->remChild(this);
+
+
+ if (d->data_ptr)
+ delete d->data_ptr;
+ }
+}
+
+QSimpleCanvasItem::operator QGraphicsItem *()
+{
+ Q_D(QSimpleCanvasItem);
+ if (!d->graphicsItem) {
+ if (parent()) {
+ qWarning("QSimpleCanvasItem: Only the root item can be converted into a QGraphicsItem");
+ return 0;
+ }
+ d->convertToGraphicsItem();
+ }
+ return d->graphicsItem;
+}
+
+QSimpleCanvasItem::operator QmlDebuggerStatus *()
+{
+ Q_D(QSimpleCanvasItem);
+ if(!d->debuggerStatus)
+ d->debuggerStatus = new QSimpleCanvasItemDebuggerStatus(this);
+ return d->debuggerStatus;
+}
+
+QPointF QSimpleCanvasItemPrivate::transformOrigin() const
+{
+ Q_Q(const QSimpleCanvasItem);
+
+ QRectF br = q->boundingRect();
+
+ switch(origin) {
+ default:
+ case QSimpleCanvasItem::TopLeft:
+ return QPointF(0, 0);
+ case QSimpleCanvasItem::TopCenter:
+ return QPointF(br.width() / 2., 0);
+ case QSimpleCanvasItem::TopRight:
+ return QPointF(br.width(), 0);
+ case QSimpleCanvasItem::MiddleLeft:
+ return QPointF(0, br.height() / 2.);
+ case QSimpleCanvasItem::Center:
+ return QPointF(br.width() / 2., br.height() / 2.);
+ case QSimpleCanvasItem::MiddleRight:
+ return QPointF(br.width(), br.height() / 2.);
+ case QSimpleCanvasItem::BottomLeft:
+ return QPointF(0, br.height());
+ case QSimpleCanvasItem::BottomCenter:
+ return QPointF(br.width() / 2., br.height());
+ case QSimpleCanvasItem::BottomRight:
+ return QPointF(br.width(), br.height());
+ }
+}
+
+void QSimpleCanvasItemPrivate::setParentInternal(QSimpleCanvasItem *p)
+{
+ Q_Q(QSimpleCanvasItem);
+ QSimpleCanvasItem *oldParent = parent;
+ if (graphicsItem) {
+ if (oldParent)
+ oldParent->remChild(q);
+
+ parent = p;
+ graphicsItem->setParentItem(p->d_func()->graphicsItem);
+
+ if (parent)
+ p->addChild(q);
+
+ } else {
+ bool canvasChange = false;
+ if (p)
+ canvasChange = (p->d_func()->canvas != canvas);
+ QSimpleCanvas *old = canvas;
+
+ QSimpleCanvasLayer *o = q->layer();
+ if (q->parent()) {
+ q->update();
+ q->parent()->remChild(q);
+ }
+ parent = p;
+ QSimpleCanvasLayer *n = 0;
+ if (q->parent()) {
+ q->parent()->addChild(q);
+ n = q->layer();
+ }
+
+ if (o != n) {
+ data()->dirty = false;
+ data()->transformValid = false;
+ if (o) o->remDirty(q);
+ if (n) n->addDirty(q);
+ }
+
+ if (canvasChange)
+ canvasChanged(p->d_func()->canvas, old);
+
+ q->update();
+ }
+}
+
+void QSimpleCanvasItemPrivate::convertToGraphicsItem(QGraphicsItem *parent)
+{
+ Q_Q(QSimpleCanvasItem);
+ Q_ASSERT(!graphicsItem);
+ graphicsItem = new QSimpleGraphicsItem(q);
+ if (parent)
+ graphicsItem->setParentItem(parent);
+
+ QSimpleCanvasItemData *old = data_ptr;
+ data_ptr = 0;
+
+ if (old) {
+ q->QSimpleCanvasItem::setX(old->x);
+ q->QSimpleCanvasItem::setY(old->y);
+ q->QSimpleCanvasItem::setZ(old->z);
+ q->QSimpleCanvasItem::setVisible(old->visible);
+ if (old->transformUser)
+ q->QSimpleCanvasItem::setTransform(*old->transformUser);
+ q->QSimpleCanvasItem::setFlip(old->flip);
+ q->QSimpleCanvasItem::setAcceptedMouseButtons((Qt::MouseButtons)old->buttons);
+ delete old;
+ }
+
+ if (scale != 1) {
+ qreal s = scale;
+ scale = 1;
+ q->QSimpleCanvasItem::setScale(s);
+ }
+
+ q->setClipType(clip);
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ static_cast<QSimpleCanvasItemPrivate*>(children.at(ii)->d_ptr)->convertToGraphicsItem(graphicsItem);
+ if (children.at(ii)->z() == 0)
+ children.at(ii)->setZ(ii);
+ }
+}
+
+/*!
+ \fn void QSimpleCanvasItem::setParent(QSimpleCanvasItem *parent)
+
+ Sets the parent of the item to \a parent.
+ */
+void QSimpleCanvasItem::setParent(QSimpleCanvasItem *p)
+{
+ Q_D(QSimpleCanvasItem);
+ if (p == parent() || !p) return;
+
+ QObject::setParent(p);
+
+ if (d->graphicsItem && !static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr)->graphicsItem)
+ qWarning("QSimpleCanvasItem: Cannot reparent a QGraphicsView item to a QSimpleCanvas item");
+
+ if (static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr)->graphicsItem && !d->graphicsItem) {
+ d->setParentInternal(0);
+ d->convertToGraphicsItem();
+ }
+
+ QSimpleCanvasItem *oldParent = d->parent;
+ d->setParentInternal(p);
+ parentChanged(p, oldParent);
+}
+
+int QSimpleCanvasItemPrivate::dump(int indent)
+{
+ Q_Q(QSimpleCanvasItem);
+ QByteArray ba(indent * 2, ' ');
+
+ QByteArray state;
+ if (options & QSimpleCanvasItem::MouseFilter)
+ state.append("i");
+ else
+ state.append("-");
+ if (options & QSimpleCanvasItem::HoverEvents)
+ state.append("h");
+ else
+ state.append("-");
+ if (options & QSimpleCanvasItem::MouseEvents)
+ state.append("m");
+ else
+ state.append("-");
+ if (options & QSimpleCanvasItem::HasContents)
+ state.append("c");
+ else
+ state.append("-");
+ if (options & QSimpleCanvasItem::SimpleItem)
+ state.append("s");
+ else
+ state.append("-");
+ if (options & QSimpleCanvasItem::IsFocusPanel) {
+ if (q->activeFocusPanel())
+ state.append("P");
+ else
+ state.append("p");
+ } else {
+ state.append("-");
+ }
+ if (options & QSimpleCanvasItem::IsFocusRealm)
+ state.append("r");
+ else
+ state.append("-");
+ if (q->hasFocus()) {
+ if (q->hasActiveFocus())
+ state.append("F");
+ else
+ state.append("f");
+ } else {
+ if (q->hasActiveFocus())
+ state.append("X");
+ else
+ state.append("-");
+ }
+
+ QByteArray name;
+ QFxItem *i = qobject_cast<QFxItem *>(q);
+ if (i)
+ name = i->id().toLatin1();
+ qWarning().nospace() << ba.constData() << state.constData() << " " << children.count() << " " << q << " " << name.constData();
+
+ int rv = 0;
+
+ for (int ii = 0; ii < children.count(); ++ii)
+ rv += children.at(ii)->d_func()->dump(indent + 1);
+
+ return rv + 1;
+}
+
+bool QSimpleCanvasItemPrivate::checkFocusState(FocusStateCheckDatas d,
+ FocusStateCheckRDatas *r)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ bool rv = true;
+ bool isRealm = (options & QSimpleCanvasItem::IsFocusPanel ||
+ options & QSimpleCanvasItem::IsFocusRealm);
+
+ if (options & QSimpleCanvasItem::IsFocusPanel) {
+
+ if (q->activeFocusPanel()) {
+ if (d & InActivePanel) {
+ qWarning() << "State ERROR: Nested active focus panels";
+ rv = false;
+ }
+
+ d |= InActivePanel;
+ } else {
+ d &= ~InActivePanel;
+ }
+
+ }
+
+ if (q->hasActiveFocus()) {
+ if (!(d & InActivePanel)) {
+ qWarning() << "State ERROR: Active focus in non-active panel";
+ rv = false;
+ }
+
+ if (d & InRealm && !(d & InActiveFocusedRealm)) {
+ qWarning() << "State ERROR: Active focus in non-active-focused realm";
+ rv = false;
+ }
+
+ if (!q->hasFocus()) {
+ qWarning() << "State ERROR: Active focus on element that does not have focus";
+ rv = false;
+ }
+
+ if (*r & SeenActiveFocus) {
+ qWarning() << "State ERROR: Two active focused elements in same realm";
+ rv = false;
+ }
+
+ *r |= SeenActiveFocus;
+ }
+
+ if (q->hasFocus()) {
+ if (*r & SeenFocus) {
+ qWarning() << "State ERROR: Two focused elements in same realm";
+ rv = false;
+ }
+
+ *r |= SeenFocus;
+ }
+
+ if (options & QSimpleCanvasItem::IsFocusRealm) {
+ d |= InRealm;
+
+ if (q->hasActiveFocus())
+ d |= InActiveFocusedRealm;
+ else
+ d &= ~InActiveFocusedRealm;
+ }
+
+ FocusStateCheckRDatas newR = NoCheckRData;
+ if (isRealm)
+ r = &newR;
+
+ for (int ii = 0; ii < children.count(); ++ii)
+ rv &= children.at(ii)->d_func()->checkFocusState(d, r);
+
+ return rv;
+}
+
+bool QSimpleCanvasItem::activeFocusPanel() const
+{
+ QSimpleCanvas *c = canvas();
+ if (!c) {
+ Q_D(const QSimpleCanvasItem);
+ return d->wantsActiveFocusPanelPendingCanvas;
+ } else {
+ return c->activeFocusPanel() == this;
+ }
+}
+
+void QSimpleCanvasItem::setActiveFocusPanel(bool b)
+{
+ if (!(options() & IsFocusPanel)) {
+ qWarning("QSimpleCanvasItem::setActiveFocusPanel: Item is not a focus panel");
+ return;
+ }
+
+ QSimpleCanvas *c = canvas();
+ Q_D(QSimpleCanvasItem);
+ if (c) {
+ if (b) {
+ d->hasBeenActiveFocusPanel = true;
+ c->d->setActiveFocusPanel(this);
+ } else if (d->hasBeenActiveFocusPanel) {
+ d->hasBeenActiveFocusPanel = false;
+ c->d->clearFocusPanel(this);
+ }
+ } else {
+ d->wantsActiveFocusPanelPendingCanvas = b;
+ }
+}
+
+bool QSimpleCanvasItem::hasActiveFocus() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->hasActiveFocus;
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::findFirstFocusChild() const
+{
+ Q_D(const QSimpleCanvasItem);
+
+ const QList<QSimpleCanvasItem *> &children = d->children;
+
+ for (int i = 0; i < children.count(); ++i) {
+ QSimpleCanvasItem *child = children.at(i);
+ if (child->options() & IsFocusPanel)
+ continue;
+
+ if (child->isFocusable())
+ return child;
+
+ QSimpleCanvasItem *testFocus = child->findFirstFocusChild();
+ if (testFocus)
+ return testFocus;
+ }
+
+ return 0;
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::findLastFocusChild() const
+{
+ Q_D(const QSimpleCanvasItem);
+
+ const QList<QSimpleCanvasItem *> &children = d->children;
+
+ for (int i = children.count()-1; i >= 0; --i) {
+ QSimpleCanvasItem *child = children.at(i);
+ if (child->options() & IsFocusPanel)
+ continue;
+
+ if (child->isFocusable())
+ return child;
+ QSimpleCanvasItem *testFocus = child->findLastFocusChild();
+ if (testFocus)
+ return testFocus;
+ }
+
+ return 0;
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::findPrevFocus(QSimpleCanvasItem *item)
+{
+ QSimpleCanvasItem *focusChild = item->findLastFocusChild();
+ if (focusChild)
+ return focusChild;
+
+ if (item->options() & IsFocusPanel) {
+ if (item->isFocusable())
+ return item;
+ else
+ return 0;
+ }
+
+ QSimpleCanvasItem *parent = item->parent();
+ while (parent) {
+ const QList<QSimpleCanvasItem *> &children = parent->d_func()->children;
+
+ int idx = children.indexOf(item);
+ QSimpleCanvasItem *testFocus = 0;
+ if (idx > 0) {
+ while (--idx >= 0) {
+ testFocus = children.at(idx);
+ if (testFocus->options() & IsFocusPanel)
+ continue;
+ if (testFocus->isFocusable())
+ return testFocus;
+ testFocus = testFocus->findLastFocusChild();
+ if (testFocus)
+ return testFocus;
+ }
+ }
+ if (parent->options() & IsFocusPanel) {
+ if (parent->isFocusable())
+ return parent;
+ else
+ return 0;
+ }
+ item = parent;
+ parent = parent->parent();
+ }
+
+ return 0;
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::findNextFocus(QSimpleCanvasItem *item)
+{
+ QSimpleCanvasItem *focusChild = item->findFirstFocusChild();
+ if (focusChild)
+ return focusChild;
+
+ if (item->options() & IsFocusPanel) {
+ if (item->isFocusable())
+ return item;
+ else
+ return 0;
+ }
+
+ QSimpleCanvasItem *parent = item->parent();
+ while (parent) {
+ const QList<QSimpleCanvasItem *> &children = parent->d_func()->children;
+
+ int idx = children.indexOf(item);
+ QSimpleCanvasItem *testFocus = 0;
+ if (idx >= 0) {
+ while (++idx < children.count()) {
+ testFocus = children.at(idx);
+ if (testFocus->options() & IsFocusPanel)
+ continue;
+ if (testFocus->isFocusable())
+ return testFocus;
+ testFocus = testFocus->findFirstFocusChild();
+ if (testFocus)
+ return testFocus;
+ }
+ }
+ if (parent->options() & IsFocusPanel) {
+ if (parent->isFocusable())
+ return parent;
+ else
+ return 0;
+ }
+ item = parent;
+ parent = parent->parent();
+ }
+
+ return 0;
+}
+
+QImage QSimpleCanvasItem::string(const QString &str, const QColor &c, const QFont &f)
+{
+ QFontMetrics fm(f);
+ QSize size(fm.width(str), fm.height()*(str.count(QLatin1Char('\n'))+1)); //fm.boundingRect(str).size();
+ QImage img(size, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+ QPainter p(&img);
+ p.setPen(c);
+ p.setFont(f);
+ p.drawText(img.rect(), Qt::AlignVCenter, str);
+ return img;
+}
+
+void QSimpleCanvasItem::geometryChanged(const QRectF &, const QRectF &)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasitem.h b/src/declarative/canvas/qsimplecanvasitem.h
new file mode 100644
index 0000000..cab8492
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasitem.h
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVASITEM_H
+#define QSIMPLECANVASITEM_H
+
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qmldebuggerstatus.h>
+#include <QtDeclarative/qsimplecanvas.h>
+#include <QtCore/qobject.h>
+#include <QtGui/qgraphicsitem.h>
+class QPainter;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QRect;
+class QSimpleCanvas;
+class QMouseEvent;
+class QKeyEvent;
+class QSimpleCanvasItemPrivate;
+class QSimpleCanvasLayer;
+class QPointF;
+class QRectF;
+class QGraphicsSceneHoverEvent;
+class QSimpleCanvasFilter;
+class GLTexture;
+class QGLShaderProgram;
+
+class Q_DECLARATIVE_EXPORT QSimpleCanvasItem : public QObject
+{
+ Q_OBJECT
+ Q_CAST_INTERFACES(QGraphicsItem)
+ Q_CAST_INTERFACES(QmlDebuggerStatus)
+ Q_DECLARE_PRIVATE(QSimpleCanvasItem)
+ Q_ENUMS(TransformOrigin)
+ Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin);
+
+public:
+ enum ClipType { NoClip = 0x00,
+ ClipToHeight = 0x01,
+ ClipToWidth = 0x02,
+ ClipToRect = 0x03 };
+ enum Option { NoOption = 0x00000000,
+ MouseFilter = 0x00000001,
+ ChildMouseFilter = 0x00000002,
+ HoverEvents = 0x00000004,
+ MouseEvents = 0x00000008,
+ HasContents = 0x00000010,
+ SimpleItem = 0x00000020,
+ IsFocusPanel = 0x00000040,
+ IsFocusRealm = 0x00000080,
+ AcceptsInputMethods = 0x00000100};
+ Q_DECLARE_FLAGS(Options, Option);
+
+ QSimpleCanvasItem(QSimpleCanvasItem *parent=0);
+ virtual ~QSimpleCanvasItem();
+ operator QGraphicsItem *();
+ operator QmlDebuggerStatus *();
+
+ bool clip() const;
+ void setClip(bool);
+ ClipType clipType() const;
+ void setClipType(ClipType);
+
+ Options options() const;
+ void setOptions(Options, bool set = true);
+
+ Qt::MouseButtons acceptedMouseButtons() const;
+ void setAcceptedMouseButtons(Qt::MouseButtons buttons);
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+ QPointF pos() const;
+ void setX(qreal);
+ void setY(qreal);
+ virtual void setZ(qreal);
+ void setPos(const QPointF &);
+
+ qreal width() const;
+ void setWidth(qreal);
+ void setImplicitWidth(qreal);
+ bool widthValid() const;
+ qreal height() const;
+ void setHeight(qreal);
+ void setImplicitHeight(qreal);
+ bool heightValid() const;
+
+ QPointF scenePos() const;
+
+ enum TransformOrigin {
+ TopLeft, TopCenter, TopRight,
+ MiddleLeft, Center, MiddleRight,
+ BottomLeft, BottomCenter, BottomRight
+ };
+ TransformOrigin transformOrigin() const;
+ void setTransformOrigin(TransformOrigin);
+ QPointF transformOriginPoint() const;
+
+
+ qreal scale() const;
+ virtual void setScale(qreal);
+
+ enum Flip { NoFlip = 0,
+ VerticalFlip = 0x01,
+ HorizontalFlip = 0x02,
+ VerticalAndHorizontalFlip = 0x03 };
+ Flip flip() const;
+ void setFlip(Flip);
+
+ qreal visible() const;
+ virtual void setVisible(qreal);
+ bool isVisible() const;
+
+ QSimpleCanvas *canvas() const;
+
+ QSimpleCanvasItem *parent() const;
+ void setParent(QSimpleCanvasItem *);
+ void stackUnder(QSimpleCanvasItem *);
+ void stackOver(QSimpleCanvasItem *);
+ void stackAt(int idx);
+ int indexForChild(QSimpleCanvasItem *);
+
+ QRect itemBoundingRect();
+
+ class GLPainter
+ {
+ public:
+ GLPainter(QSimpleCanvasItem *i) : item(i), activeOpacity(1) {}
+ QSimpleCanvasItem *item;
+ QSimpleCanvas::Matrix activeTransform;
+ qreal activeOpacity;
+ QRect sceneClipRect;
+
+ QGLShaderProgram *useTextureShader();
+ QGLShaderProgram *useColorShader(const QColor &);
+ void drawImage(const QPointF &, const GLTexture &);
+ void drawImage(const QRectF &, const GLTexture &);
+ private:
+ GLPainter(const GLPainter &);
+ GLPainter &operator=(const GLPainter &);
+ };
+
+
+ QRectF boundingRect() const;
+ virtual void paintContents(QPainter &);
+ virtual void paintGLContents(GLPainter &);
+ virtual uint glSimpleItemData(float *vertices, float *texVertices,
+ GLTexture **texture, uint count);
+
+ void update();
+
+ virtual QSimpleCanvasLayer *layer();
+
+ bool hasChildren() const;
+ const QList<QSimpleCanvasItem *> &children() const;
+
+ QPointF mapFromScene(const QPointF &) const;
+ QRectF mapFromScene(const QRectF &) const;
+ QPointF mapToScene(const QPointF &) const;
+ QRectF mapToScene(const QRectF &) const;
+
+ QSimpleCanvas::Matrix transform() const;
+ void setTransform(const QSimpleCanvas::Matrix &);
+
+ QSimpleCanvasFilter *filter() const;
+ void setFilter(QSimpleCanvasFilter *);
+
+ QSimpleCanvasItem *mouseGrabberItem() const;
+ void ungrabMouse();
+ void grabMouse();
+
+ virtual bool isFocusable() const;
+ void setFocusable(bool);
+ virtual bool hasFocus() const;
+ void setFocus(bool);
+ bool activeFocusPanel() const;
+ void setActiveFocusPanel(bool);
+
+ bool hasActiveFocus() const;
+
+ QSimpleCanvasItem *findFirstFocusChild() const;
+ QSimpleCanvasItem *findLastFocusChild() const;
+ static QSimpleCanvasItem *findPrevFocus(QSimpleCanvasItem *item);
+ static QSimpleCanvasItem *findNextFocus(QSimpleCanvasItem *item);
+
+ GLBasicShaders *basicShaders() const;
+
+ static QImage string(const QString &, const QColor & = Qt::black, const QFont & = QFont());
+
+protected:
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ virtual void addChild(QSimpleCanvasItem *);
+ virtual void remChild(QSimpleCanvasItem *);
+ virtual void canvasChanged();
+ virtual void childrenChanged();
+ virtual void parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *);
+ virtual void focusChanged(bool);
+ virtual void activeFocusChanged(bool);
+ virtual bool eventFilter(QObject *, QEvent *);
+
+public:
+ // Events
+ virtual bool mouseFilter(QGraphicsSceneMouseEvent *);
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *);
+ virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *);
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseUngrabEvent();
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+ virtual void focusOutEvent(QFocusEvent *e);
+ virtual void focusInEvent(QFocusEvent *e);
+ virtual void activePanelInEvent();
+ virtual void activePanelOutEvent();
+ virtual void inputMethodEvent(QInputMethodEvent* event);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+
+private:
+ friend class QSimpleCanvas;
+ friend class QSimpleCanvasPrivate;
+ friend class QSimpleCanvasRootLayer;
+ friend class QSimpleCanvasItem::GLPainter;
+ friend class QSimpleCanvasFilter;
+ friend class QGraphicsQSimpleCanvasItem;
+ friend class QSimpleGraphicsItem;
+ friend class CanvasEGLWidget;
+ friend class QSimpleCanvasFilterPrivate;
+
+public:
+ QSimpleCanvasItem(QSimpleCanvasItemPrivate &dd, QSimpleCanvasItem *parent);
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSimpleCanvasItem::Options);
+
+class QSimpleCanvasLayer : public QSimpleCanvasItem
+{
+public:
+ QSimpleCanvasLayer(QSimpleCanvasItem *parent);
+
+ virtual void addChild(QSimpleCanvasItem *);
+ virtual void addDirty(QSimpleCanvasItem *);
+ virtual void remDirty(QSimpleCanvasItem *);
+ virtual QSimpleCanvasLayer *layer();
+
+private:
+ friend class QSimpleCanvas;
+ friend class QSimpleCanvasRootLayer;
+ QSimpleCanvasLayer();
+};
+
+
+
+#endif // _GFXCANVASITEM_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/canvas/qsimplecanvasitem_p.h b/src/declarative/canvas/qsimplecanvasitem_p.h
new file mode 100644
index 0000000..cfe0bba
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasitem_p.h
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVASITEM_P_H
+#define QSIMPLECANVASITEM_P_H
+
+#include "private/qobject_p.h"
+#include "qsimplecanvas.h"
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvasfilter.h"
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glbasicshaders.h>
+#endif
+
+#include "qgraphicsitem.h"
+
+
+QT_BEGIN_NAMESPACE
+class QSimpleGraphicsItem : public QGraphicsItem
+{
+public:
+ QSimpleGraphicsItem(QSimpleCanvasItem *);
+ virtual ~QSimpleGraphicsItem();
+
+ virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+ virtual QRectF boundingRect() const;
+
+ QTransform transform;
+protected:
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ virtual bool sceneEvent(QEvent *);
+ virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+ virtual void focusInEvent(QFocusEvent *event);
+
+private:
+ friend class QSimpleCanvasItem;
+ QSimpleCanvasItem *owner;
+};
+
+class QSimpleCanvasItemData
+{
+public:
+ QSimpleCanvasItemData();
+ ~QSimpleCanvasItemData();
+
+ // 5 bits is all that's needed to store Qt::MouseButtons
+ int buttons:5;
+ QSimpleCanvasItem::Flip flip:2;
+ bool dirty:1;
+ bool transformValid:1;
+
+ qreal x;
+ qreal y;
+ qreal z;
+ float visible;
+
+ QSimpleCanvas::Matrix *transformUser;
+ QSimpleCanvas::Matrix transformActive;
+
+ float activeOpacity;
+
+#if defined(QFX_RENDER_OPENGL)
+ QRectF lastPaintRect;
+#else
+ QRect lastPaintRect;
+#endif
+};
+
+class QSimpleCanvasItemDebuggerStatus : public QmlDebuggerStatus
+{
+public:
+ QSimpleCanvasItemDebuggerStatus(QSimpleCanvasItem *i)
+ : item(i), selected(false) {}
+
+ virtual void setSelectedState(bool state)
+ {
+ selected = state;
+ item->update();
+ }
+
+ QSimpleCanvasItem *item;
+ bool selected;
+};
+
+class QSimpleCanvasFilter;
+class QGraphicsQSimpleCanvasItem;
+class QSimpleCanvasItemPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSimpleCanvasItem);
+public:
+ QSimpleCanvasItemPrivate()
+ : parent(0), canvas(0), debuggerStatus(0), filter(0),
+ clip(QSimpleCanvasItem::NoClip),
+ origin(QSimpleCanvasItem::TopLeft), options(QSimpleCanvasItem::NoOption),
+ focusable(false), wantsActiveFocusPanelPendingCanvas(false),
+ hasBeenActiveFocusPanel(false),
+ hasFocus(false), hasActiveFocus(false), needsZOrder(false),
+ widthValid(false), heightValid(false), width(0), height(0), scale(1),
+ graphicsItem(0), data_ptr(0)
+ {
+ }
+
+ virtual ~QSimpleCanvasItemPrivate()
+ {
+ if(debuggerStatus) delete debuggerStatus;
+ }
+
+ QSimpleCanvasItem *parent;
+ QSimpleCanvas *canvas;
+ QList<QSimpleCanvasItem *> children;
+
+ QSimpleCanvasItemDebuggerStatus *debuggerStatus;
+ QSimpleCanvasFilter *filter;
+
+ QSimpleCanvasItem::ClipType clip:3;
+ QSimpleCanvasItem::TransformOrigin origin:4;
+ int options:9;
+ bool focusable:1;
+ bool wantsActiveFocusPanelPendingCanvas:1;
+ bool hasBeenActiveFocusPanel:1;
+ bool hasFocus:1;
+ bool hasActiveFocus:1;
+ bool needsZOrder:1;
+ bool widthValid:1;
+ bool heightValid:1;
+
+ void setFocus(bool f);
+ void setActiveFocus(bool f);
+
+ qreal width;
+ qreal height;
+ qreal scale;
+
+ QSimpleGraphicsItem *graphicsItem;
+ inline QSimpleCanvasItemData *data() const {
+ if (!data_ptr) data_ptr = new QSimpleCanvasItemData;
+ return data_ptr;
+ }
+ mutable QSimpleCanvasItemData *data_ptr;
+
+ void gvRemoveMouseFilter();
+ void gvAddMouseFilter();
+
+ void canvasChanged(QSimpleCanvas *newCanvas, QSimpleCanvas *oldCanvas);
+
+ void freshenTransforms() const;
+
+ QPointF adjustFrom(const QPointF &) const;
+ QRectF adjustFrom(const QRectF &) const;
+ QPointF adjustTo(const QPointF &) const;
+ QRectF adjustTo(const QRectF &) const;
+
+ QPointF transformOrigin() const;
+
+ void setParentInternal(QSimpleCanvasItem *);
+ void convertToGraphicsItem(QGraphicsItem * = 0);
+
+#if defined(QFX_RENDER_QPAINTER)
+ void paint(QPainter &);
+ void paintChild(QPainter &, QSimpleCanvasItem *);
+ QRect setupPainting(int version, const QRect &bounding);
+#else
+ struct GLPaintParameters
+ {
+ QRect sceneRect;
+ QRectF boundingRect;
+ QRect clipRect;
+#if defined(QFX_RENDER_OPENGL2)
+ uchar stencilValue;
+#endif
+ float opacity;
+ bool forceParamRefresh;
+ };
+#if defined(QFX_RENDER_OPENGL2)
+ QRectF setupPainting(int version, const QRect &bounding);
+#elif defined(QFX_RENDER_OPENGL1)
+ QRectF setupPainting(int version, const QRect &bounding, unsigned int *zero);
+#endif
+ void setupChildState(QSimpleCanvasItem *);
+
+ void paint(GLPaintParameters &, QSimpleCanvasFilter::Layer = QSimpleCanvasFilter::All);
+#if defined(QFX_RENDER_OPENGL1)
+ void paintNoClip(GLPaintParameters &, QSimpleCanvasFilter::Layer = QSimpleCanvasFilter::All);
+#endif
+ void paintChild(const GLPaintParameters &, QSimpleCanvasItem *);
+ void simplePaintChild(const GLPaintParameters &, QSimpleCanvasItem *);
+
+ inline GLBasicShaders *basicShaders() const;
+
+ QSimpleCanvas::Matrix localTransform() const;
+
+#endif
+
+ void zOrderChildren();
+ static int nextTransformVersion;
+ bool freshenNeeded() const;
+ void doFreshenTransforms() const;
+
+ // Debugging
+ int dump(int);
+ enum FocusStateCheckData { NoCheckData = 0x00,
+ InActivePanel = 0x01,
+ InRealm = 0x02,
+ InActiveFocusedRealm = 0x04
+ };
+ Q_DECLARE_FLAGS(FocusStateCheckDatas, FocusStateCheckData);
+ enum FocusStateCheckRData { NoCheckRData = 0x00,
+ SeenFocus = 0x01,
+ SeenActiveFocus = 0x02 };
+ Q_DECLARE_FLAGS(FocusStateCheckRDatas, FocusStateCheckRData);
+ bool checkFocusState(FocusStateCheckDatas, FocusStateCheckRDatas *);
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSimpleCanvasItemPrivate::FocusStateCheckDatas);
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSimpleCanvasItemPrivate::FocusStateCheckRDatas);
+
+#endif // QSIMPLECANVASITEM_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasserver.cpp b/src/declarative/canvas/qsimplecanvasserver.cpp
new file mode 100644
index 0000000..4d4adda
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasserver.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimplecanvasserver_p.h"
+#include "qdebug.h"
+#ifndef Q_OS_WIN32
+#include <arpa/inet.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QSimpleCanvasServer::QSimpleCanvasServer(int port, QObject *parent)
+: QObject(parent), _tcpServer(new QTcpServer(this))
+{
+ QObject::connect(_tcpServer, SIGNAL(newConnection()),
+ this, SLOT(newConnection()));
+
+ _time.start();
+
+ if (!_tcpServer->listen(QHostAddress::Any, port)) {
+ qWarning() << "QSimpleCanvasServer: Cannot listen on port" << port;
+ return;
+ }
+}
+
+void QSimpleCanvasServer::newConnection()
+{
+ QTcpSocket *socket = _tcpServer->nextPendingConnection();
+ QObject::connect(socket, SIGNAL(disconnected()),
+ this, SLOT(disconnected()));
+ _tcpClients << socket;
+}
+
+void QSimpleCanvasServer::addTiming(quint32 paint,
+ quint32 repaint,
+ quint32 timeBetweenFrames)
+{
+ /*
+ quint32 data[3];
+ data[0] = ::htonl(paint);
+ data[1] = ::htonl(repaint);
+ data[2] = ::htonl(timeBetweenFrames);
+ */
+
+ int e = _time.elapsed();
+ QString d = QString::number(paint) + QLatin1String(" ") + QString::number(repaint) + QLatin1String(" ") + QString::number(timeBetweenFrames) + QLatin1String(" ") + QString::number(e) + QLatin1String("\n");
+ QByteArray ba = d.toLatin1();
+
+ // XXX
+ for (int ii = 0; ii < _tcpClients.count(); ++ii)
+// _tcpClients.at(ii)->write((const char *)data, 12);
+ _tcpClients.at(ii)->write(ba.constData(), ba.length());
+}
+
+void QSimpleCanvasServer::disconnected()
+{
+ QTcpSocket *socket = static_cast<QTcpSocket *>(sender());
+
+ for (int ii = 0; ii < _tcpClients.count(); ++ii) {
+ if (_tcpClients.at(ii) == socket) {
+ socket->disconnect();
+ socket->deleteLater();
+ _tcpClients.removeAt(ii);
+ return;
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasserver_p.h b/src/declarative/canvas/qsimplecanvasserver_p.h
new file mode 100644
index 0000000..7d53357
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasserver_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMPLECANVASSERVER_P_H
+#define QSIMPLECANVASSERVER_P_H
+
+#include "qobject.h"
+#include "qtcpserver.h"
+#include "qtcpsocket.h"
+#include "qdatetime.h"
+
+
+QT_BEGIN_NAMESPACE
+class QSimpleCanvasServer : public QObject
+{
+Q_OBJECT
+public:
+ QSimpleCanvasServer(int port, QObject *parent);
+
+ void addTiming(quint32, quint32, quint32);
+
+private Q_SLOTS:
+ void newConnection();
+ void disconnected();
+
+private:
+ QTcpServer *_tcpServer;
+ QList<QTcpSocket *> _tcpClients;
+ QTime _time;
+};
+
+QT_END_NAMESPACE
+#endif // GFXCANVASSERVER_P_H
diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri
new file mode 100644
index 0000000..c386d74
--- /dev/null
+++ b/src/declarative/debugger/debugger.pri
@@ -0,0 +1,13 @@
+SOURCES += debugger/qmldebugger.cpp \
+ debugger/qmldebuggerstatus.cpp \
+ debugger/qmlpropertyview.cpp \
+ debugger/qmlwatches.cpp \
+ debugger/qmlobjecttree.cpp \
+ debugger/qmlcanvasdebugger.cpp
+
+HEADERS += debugger/qmldebugger.h \
+ debugger/qmldebuggerstatus.h \
+ debugger/qmlpropertyview_p.h \
+ debugger/qmlwatches_p.h \
+ debugger/qmlobjecttree_p.h \
+ debugger/qmlcanvasdebugger_p.h
diff --git a/src/declarative/debugger/qmlcanvasdebugger.cpp b/src/declarative/debugger/qmlcanvasdebugger.cpp
new file mode 100644
index 0000000..fe57bf4
--- /dev/null
+++ b/src/declarative/debugger/qmlcanvasdebugger.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qmlcanvasdebugger_p.h>
+#include <private/qmlwatches_p.h>
+#include <QtDeclarative/qsimplecanvas.h>
+#include <QtGui/qboxlayout.h>
+#include <QtGui/qpushbutton.h>
+#include <QtGui/qspinbox.h>
+#include <QtGui/qsplitter.h>
+#include <QtGui/qtreewidget.h>
+
+#include <QtDeclarative/qfxrect.h>
+#include <QtDeclarative/qfximage.h>
+
+QmlCanvasDebugger::QmlCanvasDebugger(QmlWatches *w, QWidget *parent)
+: QWidget(parent), m_watches(w), m_tree(0), m_canvas(0), m_canvasRoot(0), m_debugCanvas(0),
+ m_selected(0)
+{
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setContentsMargins(0,0,0,0);
+ layout->setSpacing(0);
+ setLayout(layout);
+ QHBoxLayout *hlayout = new QHBoxLayout;
+ hlayout->setContentsMargins(0,0,0,0);
+ hlayout->addStretch(2);
+ hlayout->setSpacing(0);
+ layout->addLayout(hlayout);
+ QSpinBox *x = new QSpinBox(this);
+ x->setSingleStep(50);
+ x->setMaximum(10000);
+ x->setMinimum(-10000);
+ QObject::connect(x, SIGNAL(valueChanged(int)), this, SLOT(setX(int)));
+ QSpinBox *y = new QSpinBox(this);
+ y->setSingleStep(50);
+ y->setMaximum(10000);
+ y->setMinimum(-10000);
+ QObject::connect(y, SIGNAL(valueChanged(int)), this, SLOT(setY(int)));
+ hlayout->addWidget(x);
+ hlayout->addWidget(y);
+ QPushButton *pb = new QPushButton("Refresh", this);
+ QObject::connect(pb, SIGNAL(clicked()), this, SLOT(refresh()));
+ hlayout->addWidget(pb);
+
+ QSplitter *splitter = new QSplitter(this);
+
+ m_tree = new QTreeWidget(this);
+ QObject::connect(m_tree, SIGNAL(itemExpanded(QTreeWidgetItem*)),
+ this, SLOT(itemExpanded(QTreeWidgetItem*)));
+ QObject::connect(m_tree, SIGNAL(itemCollapsed(QTreeWidgetItem*)),
+ this, SLOT(itemCollapsed(QTreeWidgetItem*)));
+ QObject::connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
+ this, SLOT(itemClicked(QTreeWidgetItem*)));
+ m_canvas = new QSimpleCanvas(QSimpleCanvas::SimpleCanvas, this);
+ m_canvasRoot = new QSimpleCanvasItem;
+ m_canvasRoot->setParent(m_canvas->root());
+ splitter->addWidget(m_tree);
+ splitter->addWidget(m_canvas);
+ splitter->setStretchFactor(1, 2);
+ layout->addWidget(splitter);
+}
+
+void QmlCanvasDebugger::refresh()
+{
+ setCanvas(m_debugCanvas);
+}
+
+class QmlCanvasDebuggerItem : public QTreeWidgetItem
+{
+public:
+ QmlCanvasDebuggerItem(QTreeWidget *tree)
+ : QTreeWidgetItem(tree), me(0), img(0)
+ {
+ }
+
+ QmlCanvasDebuggerItem(QTreeWidgetItem *item)
+ : QTreeWidgetItem(item), me(0), img(0)
+ {
+ }
+
+ QPointer<QObject> them;
+ QFxRect *me;
+ QFxImage *img;
+};
+
+void QmlCanvasDebugger::itemExpanded(QTreeWidgetItem *i)
+{
+ QmlCanvasDebuggerItem *item = static_cast<QmlCanvasDebuggerItem *>(i);
+ if(item->me)
+ item->me->setOpacity(1);
+}
+
+void QmlCanvasDebugger::setOpacityRecur(QTreeWidgetItem *i, qreal op)
+{
+ QmlCanvasDebuggerItem *item = static_cast<QmlCanvasDebuggerItem *>(i);
+ if(item->img)
+ item->img->setOpacity(op);
+
+ for(int ii = 0; ii < item->childCount(); ++ii)
+ setOpacityRecur(item->child(ii), op);
+}
+
+void QmlCanvasDebugger::itemClicked(QTreeWidgetItem *i)
+{
+ QmlCanvasDebuggerItem *item = static_cast<QmlCanvasDebuggerItem *>(i);
+ if(item->them)
+ emit objectClicked(m_watches->objectId(item->them));
+
+ if(m_selected) {
+ setOpacityRecur(m_selected, 0);
+ m_selected = 0;
+ }
+
+ m_selected = item;
+ setOpacityRecur(m_selected, 1);
+}
+
+void QmlCanvasDebugger::itemCollapsed(QTreeWidgetItem *i)
+{
+ QmlCanvasDebuggerItem *item = static_cast<QmlCanvasDebuggerItem *>(i);
+ if(item->me)
+ item->me->setOpacity(0);
+}
+
+void QmlCanvasDebugger::clone(QTreeWidgetItem *item, QSimpleCanvasItem *me, QSimpleCanvasItem *them)
+{
+ const QList<QSimpleCanvasItem *> &children = them->children();
+
+ foreach(QSimpleCanvasItem *child, children) {
+ QmlCanvasDebuggerItem *childItem = new QmlCanvasDebuggerItem(item);
+ childItem->setText(0, QmlWatches::objectToString(child));
+ childItem->setExpanded(true);
+
+ QFxRect *rect = new QFxRect;
+ rect->setParent(me);
+ rect->setX(child->x());
+ rect->setY(child->y());
+ rect->setZ(child->z());
+ rect->setWidth(child->width());
+ rect->setHeight(child->height());
+ rect->setTransformOrigin(child->transformOrigin());
+ rect->setScale(child->scale());
+ rect->setFlip(child->flip());
+ rect->setTransform(child->transform());
+
+ if(child->hasActiveFocus())
+ rect->setColor(QColor(0, 0, 0, 10));
+ else if(child->options() & QSimpleCanvasItem::IsFocusPanel)
+ rect->setColor(QColor(0, 255, 0, 10));
+ else if(child->options() & QSimpleCanvasItem::IsFocusRealm)
+ rect->setColor(QColor(0, 0, 255, 10));
+ else
+ rect->setColor(QColor(255, 0, 0, 10));
+
+ if(child->width() > 0 && child->height() > 0) {
+ QPixmap pix(child->width(), child->height());
+ pix.fill(QColor(0,0,0,0));
+ QPainter p(&pix);
+ child->paintContents(p);
+ QFxImage *img = new QFxImage;
+ img->setParent(rect);
+ img->setWidth(child->width());
+ img->setHeight(child->height());
+ img->setPixmap(pix);
+ img->setOpacity(0);
+ childItem->img = img;
+ }
+
+ childItem->them = child;
+ childItem->me = rect;
+
+ clone(childItem, rect, child);
+ }
+}
+
+void QmlCanvasDebugger::setX(int x)
+{
+ m_canvasRoot->setX(x);
+}
+
+void QmlCanvasDebugger::setY(int y)
+{
+ m_canvasRoot->setY(y);
+}
+
+void QmlCanvasDebugger::setCanvas(QSimpleCanvas *canvas)
+{
+ QList<QSimpleCanvasItem *> children = m_canvasRoot->children();
+ qDeleteAll(children);
+ m_tree->clear();
+ m_selected = 0;
+
+ m_debugCanvas = canvas;
+ if(!m_debugCanvas)
+ return;
+
+ QTreeWidgetItem *root = new QmlCanvasDebuggerItem(m_tree);
+ root->setText(0, "Root");
+ root->setExpanded(true);
+ clone(root, m_canvasRoot, m_debugCanvas->root());
+}
+
diff --git a/src/declarative/debugger/qmlcanvasdebugger_p.h b/src/declarative/debugger/qmlcanvasdebugger_p.h
new file mode 100644
index 0000000..80a2322
--- /dev/null
+++ b/src/declarative/debugger/qmlcanvasdebugger_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCANVASDEBUGGER_P_H
+#define QMLCANVASDEBUGGER_P_H
+
+#include <QtGui/qwidget.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSimpleCanvas;
+class QSimpleCanvasItem;
+class QTreeWidget;
+class QTreeWidgetItem;
+class QmlWatches;
+class QmlCanvasDebugger : public QWidget
+{
+ Q_OBJECT
+public:
+ QmlCanvasDebugger(QmlWatches *, QWidget *parent = 0);
+
+ void setCanvas(QSimpleCanvas *);
+
+signals:
+ void objectClicked(quint32);
+
+private slots:
+ void refresh();
+ void itemClicked(QTreeWidgetItem *);
+ void itemExpanded(QTreeWidgetItem *);
+ void itemCollapsed(QTreeWidgetItem *);
+ void setX(int);
+ void setY(int);
+
+private:
+ void setOpacityRecur(QTreeWidgetItem *, qreal);
+ void clone(QTreeWidgetItem *, QSimpleCanvasItem *me, QSimpleCanvasItem *them);
+
+ QmlWatches *m_watches;
+ QTreeWidget *m_tree;
+ QSimpleCanvas *m_canvas;
+ QSimpleCanvasItem *m_canvasRoot;
+ QPointer<QSimpleCanvas> m_debugCanvas;
+ QTreeWidgetItem *m_selected;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCANVASDEBUGGER_P_H
+
diff --git a/src/declarative/debugger/qmldebugger.cpp b/src/declarative/debugger/qmldebugger.cpp
new file mode 100644
index 0000000..49ad8d9
--- /dev/null
+++ b/src/declarative/debugger/qmldebugger.cpp
@@ -0,0 +1,361 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldebugger.h"
+#include <QtGui/qtreewidget.h>
+#include <QtGui/qboxlayout.h>
+#include <QtGui/qplaintextedit.h>
+#include <QTextBlock>
+#include <QtGui/qtabwidget.h>
+#include <QtDeclarative/qmlbindablevalue.h>
+#include <QtDeclarative/qmldebuggerstatus.h>
+#include <private/qmlboundsignal_p.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlobjecttree_p.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qurl.h>
+#include <QtGui/qsplitter.h>
+#include <QtGui/qpushbutton.h>
+#include <QtGui/qtablewidget.h>
+#include <QtGui/qevent.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <private/qmlpropertyview_p.h>
+#include <private/qmlwatches_p.h>
+#include <private/qmlcanvasdebugger_p.h>
+
+QmlDebugger::QmlDebugger(QWidget *parent)
+: QWidget(parent), m_tree(0), m_warnings(0), m_watchTable(0), m_watches(0),
+ m_canvas(0), m_properties(0), m_text(0), m_highlightedItem(0)
+{
+ QHBoxLayout *layout = new QHBoxLayout;
+ setLayout(layout);
+ QSplitter *splitter = new QSplitter(this);
+ layout->addWidget(splitter);
+
+ QWidget *treeWid = new QWidget(this);
+ QVBoxLayout *vlayout = new QVBoxLayout;
+ vlayout->setContentsMargins(0, 0, 0, 0);
+ treeWid->setLayout(vlayout);
+ splitter->addWidget(treeWid);
+
+ m_tree = new QmlObjectTree(treeWid);
+ m_tree->setHeaderHidden(true);
+ QObject::connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(itemClicked(QTreeWidgetItem *)));
+ QObject::connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem *)));
+ QObject::connect(m_tree, SIGNAL(addWatch(QObject*,QString)), this, SLOT(addWatch(QObject*,QString)));
+ vlayout->addWidget(m_tree);
+
+ QPushButton *pb = new QPushButton("Refresh", treeWid);
+ QObject::connect(pb, SIGNAL(clicked()), this, SLOT(refresh()));
+ vlayout->addWidget(pb);
+
+ QTabWidget *tabs = new QTabWidget(this);
+
+ m_text = new QPlainTextEdit(this);
+ m_text->setReadOnly(true);
+ tabs->addTab(m_text, "File");
+
+ m_warnings = new QTreeWidget(this);
+ m_warnings->setHeaderHidden(true);
+ tabs->addTab(m_warnings, "Warnings");
+
+ m_watches = new QmlWatches(this);
+ m_watchTable = new QTableView(this);
+ m_watchTable->setSelectionMode(QTableWidget::NoSelection);
+ m_watchTable->setModel(m_watches);
+ tabs->addTab(m_watchTable, "Watches");
+
+ m_properties = new QmlPropertyView(m_watches, this);
+ QObject::connect(m_properties, SIGNAL(objectClicked(quint32)),
+ this, SLOT(highlightObject(quint32)));
+ tabs->addTab(m_properties, "Properties");
+ tabs->setCurrentWidget(m_properties);
+
+ m_canvas = new QmlCanvasDebugger(m_watches, this);
+ QObject::connect(m_canvas, SIGNAL(objectClicked(quint32)),
+ this, SLOT(highlightObject(quint32)));
+ tabs->addTab(m_canvas, "Canvas");
+
+ splitter->addWidget(tabs);
+ splitter->setStretchFactor(1, 2);
+
+ setGeometry(0, 100, 800, 600);
+}
+
+void QmlDebugger::itemDoubleClicked(QTreeWidgetItem *)
+{
+}
+
+void QmlDebugger::addWatch(QObject *obj, const QString &expr)
+{
+ QmlContext *ctxt = qmlContext(obj);
+ if(ctxt) {
+ QmlExpressionObject *e= new QmlExpressionObject(ctxt, expr, obj, m_watches);
+ m_watches->addWatch(e);
+ }
+}
+
+void QmlDebugger::highlightObject(quint32 id)
+{
+ QHash<quint32, QTreeWidgetItem *>::ConstIterator iter = m_items.find(id);
+ if (m_highlightedItem) {
+ m_highlightedItem->setBackground(0, QPalette().base());
+ m_highlightedItem = 0;
+ }
+
+ if (iter != m_items.end()) {
+ m_highlightedItem = *iter;
+ m_highlightedItem->setBackground(0, QColor("cyan"));
+ m_tree->expandItem(m_highlightedItem);
+ m_tree->scrollToItem(m_highlightedItem);
+ }
+}
+
+void QmlDebugger::itemClicked(QTreeWidgetItem *i)
+{
+ QmlDebuggerItem *item = static_cast<QmlDebuggerItem *>(i);
+
+ if(m_selectedItem) {
+ QmlDebuggerStatus *debug =
+ qobject_cast<QmlDebuggerStatus *>(m_selectedItem);
+ Q_ASSERT(debug);
+ debug->setSelectedState(false);
+ m_selectedItem = 0;
+ }
+
+ if(item->object) {
+ QmlDebuggerStatus *debug =
+ qobject_cast<QmlDebuggerStatus *>(item->object);
+ if(debug) {
+ debug->setSelectedState(true);
+ m_selectedItem = item->object;
+ }
+
+ m_properties->setObject(item->object);
+ }
+
+ if(item->url.scheme() == QLatin1String("file")) {
+ QString f = item->url.toLocalFile();
+ QFile file(f);
+ file.open(QIODevice::ReadOnly);
+ QByteArray ba = file.readAll();
+ QTextStream stream(ba, QIODevice::ReadOnly);
+ const QString code = stream.readAll();
+
+ m_text->setPlainText(code);
+
+ if(item->startLine != -1) {
+ QTextDocument *document = m_text->document();
+ QTextCharFormat format;
+ format.setForeground(Qt::lightGray);
+
+ {
+ QTextCursor cursor(document);
+ cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, item->endLine);
+ cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+ cursor.setCharFormat(format);
+ }
+
+ {
+ QTextCursor cursor(document);
+ cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, item->startLine - 1);
+ cursor.setCharFormat(format);
+ }
+
+ {
+ QTextCursor cursor(document);
+ cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, item->startLine - 1);
+ m_text->setTextCursor(cursor);
+ m_text->centerCursor();
+ }
+
+
+ }
+
+ }
+}
+
+bool QmlDebugger::makeItem(QObject *obj, QmlDebuggerItem *item)
+{
+ bool rv = true;
+
+ QString text;
+
+ item->object = obj;
+
+ if(QmlBindableValue *bv = qobject_cast<QmlBindableValue *>(obj)) {
+ QmlExpressionPrivate *p = bv->d;
+
+ text = bv->property().name() + ": " + bv->expression();
+ item->setForeground(0, Qt::green);
+ item->bindableValue = bv;
+
+ if(p->log) {
+ QTreeWidgetItem *warningItem = 0;
+
+ for(int ii = 0; ii < p->log->count(); ++ii) {
+ const QmlExpressionLog &log = p->log->at(ii);
+
+ QString variant; QDebug d(&variant); d << log.result();
+
+ if(!log.warnings().isEmpty()) {
+
+ if(!warningItem) {
+ warningItem = new QTreeWidgetItem(m_warnings);
+ warningItem->setText(0, bv->expression());
+ }
+
+ QTreeWidgetItem *entry = new QTreeWidgetItem(warningItem);
+ entry->setExpanded(true);
+
+ entry->setText(0, variant);
+
+ foreach(const QString &warning, log.warnings()) {
+ QTreeWidgetItem *w = new QTreeWidgetItem(entry);
+ w->setText(0, warning);
+ }
+ }
+
+ }
+
+ }
+
+ delete item;
+ return false;
+
+ } else if(QmlBoundSignal *bs = qobject_cast<QmlBoundSignal *>(obj)) {
+ delete item;
+ return false;
+ } else {
+ QmlContext *context = qmlContext(obj);
+ QmlContext *parentContext = qmlContext(obj->parent());
+
+ text = QLatin1String(obj->metaObject()->className());
+
+ if(context && context != parentContext) {
+ QmlContextPrivate *p = static_cast<QmlContextPrivate *>(QObjectPrivate::get(context));
+
+ QString toolTipString;
+ if(!p->url.toString().isEmpty()) {
+ item->url = p->url;
+ toolTipString = "URL: " + p->url.toString();
+ }
+
+ if(!p->typeName.isEmpty()) {
+ if(!toolTipString.isEmpty())
+ toolTipString.prepend("\n");
+ toolTipString.prepend("Root type: " + text);
+ text = p->typeName;
+ }
+
+ if(!toolTipString.isEmpty())
+ item->setToolTip(0, toolTipString);
+
+ item->setForeground(0, QColor("orange"));
+
+ if(p->startLine != -1) {
+ item->startLine = p->startLine;
+ item->endLine = p->endLine;
+ }
+
+ } else {
+ item->setExpanded(true);
+ }
+
+ if(!context)
+ item->setForeground(0, Qt::lightGray);
+ }
+
+ m_items.insert(m_watches->objectId(obj), item);
+ item->setText(0, text);
+
+ return rv;
+}
+
+void QmlDebugger::buildTree(QObject *obj, QmlDebuggerItem *parent)
+{
+ QObjectList children = obj->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QmlDebuggerItem *item = new QmlDebuggerItem(parent);
+ if(makeItem(children.at(ii), item))
+ buildTree(children.at(ii), item);
+ }
+}
+
+void QmlDebugger::refresh()
+{
+ setDebugObject(m_object);
+}
+
+bool operator<(const QPair<quint32, QPair<int, QString> > &lhs,
+ const QPair<quint32, QPair<int, QString> > &rhs)
+{
+ return lhs.first < rhs.first;
+}
+
+void QmlDebugger::setCanvas(QSimpleCanvas *c)
+{
+ m_canvas->setCanvas(c);
+}
+
+void QmlDebugger::setDebugObject(QObject *obj)
+{
+ m_tree->clear();
+ m_warnings->clear();
+ m_items.clear();
+ m_highlightedItem = 0;
+
+ m_object = obj;
+ if(!obj)
+ return;
+
+ QmlDebuggerItem *item = new QmlDebuggerItem(m_tree);
+ makeItem(obj, item);
+ buildTree(obj, item);
+ item->setExpanded(true);
+}
+
diff --git a/src/declarative/debugger/qmldebugger.h b/src/declarative/debugger/qmldebugger.h
new file mode 100644
index 0000000..4641bce
--- /dev/null
+++ b/src/declarative/debugger/qmldebugger.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDEBUGGER_H
+#define QMLDEBUGGER_H
+
+#include <QtCore/qpointer.h>
+#include <QtCore/qset.h>
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QTreeWidget;
+class QTreeWidgetItem;
+class QPlainTextEdit;
+class QmlDebuggerItem;
+class QTableView;
+class QmlPropertyView;
+class QmlWatches;
+class QmlObjectTree;
+class QmlContext;
+class QmlCanvasDebugger;
+class QSimpleCanvas;
+class QmlDebugger : public QWidget
+{
+Q_OBJECT
+public:
+ QmlDebugger(QWidget *parent = 0);
+
+ void setDebugObject(QObject *);
+ void setCanvas(QSimpleCanvas *);
+
+public slots:
+ void refresh();
+
+private slots:
+ void itemClicked(QTreeWidgetItem *);
+ void itemDoubleClicked(QTreeWidgetItem *);
+ void highlightObject(quint32);
+ void addWatch(QObject *, const QString &);
+
+private:
+ void buildTree(QObject *obj, QmlDebuggerItem *parent);
+ bool makeItem(QObject *obj, QmlDebuggerItem *item);
+ QmlObjectTree *m_tree;
+ QTreeWidget *m_warnings;
+ QTableView *m_watchTable;
+ QmlWatches *m_watches;
+ QmlCanvasDebugger *m_canvas;
+ QmlPropertyView *m_properties;
+ QPlainTextEdit *m_text;
+ QPointer<QObject> m_object;
+ QPointer<QObject> m_selectedItem;
+
+ QTreeWidgetItem *m_highlightedItem;
+ QHash<quint32, QTreeWidgetItem *> m_items;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDEBUGGER_H
+
diff --git a/src/declarative/debugger/qmldebuggerstatus.cpp b/src/declarative/debugger/qmldebuggerstatus.cpp
new file mode 100644
index 0000000..d46a21d
--- /dev/null
+++ b/src/declarative/debugger/qmldebuggerstatus.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldebuggerstatus.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlDebuggerStatus::~QmlDebuggerStatus()
+{
+}
+
+void QmlDebuggerStatus::setSelectedState(bool)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qmldebuggerstatus.h b/src/declarative/debugger/qmldebuggerstatus.h
new file mode 100644
index 0000000..8c6355d
--- /dev/null
+++ b/src/declarative/debugger/qmldebuggerstatus.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDEBUGGERSTATUS_P_H
+#define QMLDEBUGGERSTATUS_P_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlDebuggerStatus
+{
+public:
+ virtual ~QmlDebuggerStatus();
+
+ virtual void setSelectedState(bool);
+};
+Q_DECLARE_INTERFACE(QmlDebuggerStatus, "com.trolltech.qml.QmlDebuggerStatus");
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QLMDEBUGGERSTATUS_P_H
+
diff --git a/src/declarative/debugger/qmlobjecttree.cpp b/src/declarative/debugger/qmlobjecttree.cpp
new file mode 100644
index 0000000..fb6825a
--- /dev/null
+++ b/src/declarative/debugger/qmlobjecttree.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qmlobjecttree_p.h>
+#include <QtDeclarative/qml.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qmenu.h>
+#include <QtCore/qlist.h>
+#include <QtGui/qaction.h>
+#include <QtGui/qinputdialog.h>
+#include <QtGui/qboxlayout.h>
+
+QmlObjectTree::QmlObjectTree(QWidget *parent)
+: QTreeWidget(parent)
+{
+}
+
+void QmlObjectTree::mousePressEvent(QMouseEvent *me)
+{
+ QTreeWidget::mousePressEvent(me);
+ if(me->button() == Qt::RightButton && me->type() == QEvent::MouseButtonPress) {
+ QAction action("Add watch...", 0);
+ QList<QAction *> actions;
+ actions << &action;
+ QmlDebuggerItem *item = static_cast<QmlDebuggerItem *>(currentItem());
+ if(item && qmlContext(item->object) &&
+ QMenu::exec(actions, me->globalPos())) {
+
+ bool ok = false;
+ QString watch = QInputDialog::getText(this, "Watch expression", "Expression:", QLineEdit::Normal, QString(), &ok);
+
+ if(ok && !watch.isEmpty())
+ emit addWatch(item->object, watch);
+ }
+ }
+}
+
diff --git a/src/declarative/debugger/qmlobjecttree_p.h b/src/declarative/debugger/qmlobjecttree_p.h
new file mode 100644
index 0000000..4e6d484
--- /dev/null
+++ b/src/declarative/debugger/qmlobjecttree_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLOBJECTTREE_P_H
+#define QMLOBJECTTREE_P_H
+
+#include <QtGui/qtreewidget.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qpointer.h>
+
+class QmlBindableValue;
+class QmlDebuggerItem : public QTreeWidgetItem
+{
+public:
+ QmlDebuggerItem(QTreeWidget *wid)
+ : QTreeWidgetItem(wid), startLine(-1), endLine(-1)
+ {
+ }
+
+ QmlDebuggerItem(QTreeWidgetItem *item)
+ : QTreeWidgetItem(item), startLine(-1), endLine(-1)
+ {
+ }
+
+ int startLine;
+ int endLine;
+ QUrl url;
+
+ QPointer<QObject> object;
+ QPointer<QmlBindableValue> bindableValue;
+};
+
+class QmlContext;
+class QmlObjectTree : public QTreeWidget
+{
+ Q_OBJECT
+public:
+ QmlObjectTree(QWidget *parent = 0);
+
+signals:
+ void addWatch(QObject *, const QString &);
+
+protected:
+ virtual void mousePressEvent(QMouseEvent *);
+};
+
+#endif // QMLOBJECTTREE_P_H
+
diff --git a/src/declarative/debugger/qmlpropertyview.cpp b/src/declarative/debugger/qmlpropertyview.cpp
new file mode 100644
index 0000000..e32393c
--- /dev/null
+++ b/src/declarative/debugger/qmlpropertyview.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpropertyview_p.h"
+#include <QtGui/qboxlayout.h>
+#include <QtGui/qtreewidget.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdebug.h>
+#include <QtDeclarative/qmlbindablevalue.h>
+#include <private/qmlboundsignal_p.h>
+
+QmlPropertyView::QmlPropertyView(QmlWatches *watches, QWidget *parent)
+: QWidget(parent), m_tree(0), m_watches(watches)
+{
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ setLayout(layout);
+
+ m_tree = new QTreeWidget(this);
+ m_tree->setHeaderLabels(QStringList() << "Property" << "Value");
+ QObject::connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
+ this, SLOT(itemDoubleClicked(QTreeWidgetItem *)));
+ QObject::connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
+ this, SLOT(itemClicked(QTreeWidgetItem *)));
+
+ m_tree->setColumnCount(2);
+
+ layout->addWidget(m_tree);
+}
+
+class QmlPropertyViewItem : public QObject, public QTreeWidgetItem
+{
+Q_OBJECT
+public:
+ QmlPropertyViewItem(QTreeWidget *widget);
+ QmlPropertyViewItem(QTreeWidgetItem *parent);
+
+ QObject *object;
+ QMetaProperty property;
+
+ quint32 exprId;
+
+public slots:
+ void refresh();
+};
+
+QmlPropertyViewItem::QmlPropertyViewItem(QTreeWidget *widget)
+: QTreeWidgetItem(widget), object(0), exprId(0)
+{
+}
+
+QmlPropertyViewItem::QmlPropertyViewItem(QTreeWidgetItem *parent)
+: QTreeWidgetItem(parent), object(0), exprId(0)
+{
+}
+
+void QmlPropertyViewItem::refresh()
+{
+ QVariant v = property.read(object);
+ QString str = v.toString();
+
+ if (QmlMetaType::isObject(v.userType()))
+ str = QmlWatches::objectToString(QmlMetaType::toQObject(v));
+
+ setText(1, str);
+}
+
+void QmlPropertyView::itemClicked(QTreeWidgetItem *i)
+{
+ QmlPropertyViewItem *item = static_cast<QmlPropertyViewItem *>(i);
+
+ if(item->object) {
+ QVariant v = item->property.read(item->object);
+ if (QmlMetaType::isObject(v.userType())) {
+ QObject *obj = QmlMetaType::toQObject(v);
+
+ if(obj) {
+ quint32 id = m_watches->objectId(obj);
+ emit objectClicked(id);
+ }
+ }
+ }
+
+}
+
+void QmlPropertyView::itemDoubleClicked(QTreeWidgetItem *i)
+{
+ QmlPropertyViewItem *item = static_cast<QmlPropertyViewItem *>(i);
+
+ if(item->object) {
+ quint32 objectId = m_watches->objectId(item->object);
+
+ if(m_watches->hasWatch(objectId, item->property.name())) {
+ m_watches->remWatch(objectId, item->property.name());
+ item->setForeground(0, Qt::black);
+ } else {
+ m_watches->addWatch(objectId, item->property.name());
+ item->setForeground(0, Qt::red);
+ }
+ }
+
+}
+
+void QmlPropertyView::setObject(QObject *object)
+{
+ m_object = object;
+
+ m_tree->clear();
+ if(!m_object)
+ return;
+
+ QMultiHash<QByteArray, QPair<QString, quint32> > bindings;
+ QHash<QByteArray, QString> sigs;
+ QObjectList children = object->children();
+
+ foreach(QObject *child, children) {
+ if(QmlBindableValue *value = qobject_cast<QmlBindableValue *>(child)) {
+ bindings.insert(value->property().name().toUtf8(), qMakePair(value->expression(), value->id()));
+ } else if(QmlBoundSignal *signal = qobject_cast<QmlBoundSignal *>(child)) {
+ QMetaMethod method = object->metaObject()->method(signal->index());
+ QByteArray sig = method.signature();
+ sigs.insert(sig, signal->expression());
+ }
+ }
+
+ quint32 objectId = m_watches->objectId(object);
+
+ const QMetaObject *mo = object->metaObject();
+ for(int ii = 0; ii < mo->propertyCount(); ++ii) {
+ QMetaProperty p = mo->property(ii);
+
+ if(QmlMetaType::isList(p.userType()) ||
+ QmlMetaType::isQmlList(p.userType()))
+ continue;
+
+ QmlPropertyViewItem *item = new QmlPropertyViewItem(m_tree);
+
+ item->object = object;
+ item->property = p;
+
+ item->setText(0, QLatin1String(p.name()));
+ if(m_watches->hasWatch(objectId, p.name()))
+ item->setForeground(0, Qt::red);
+
+ static int refreshIdx = -1;
+ if(refreshIdx == -1)
+ refreshIdx = QmlPropertyViewItem::staticMetaObject.indexOfMethod("refresh()");
+
+ if(p.hasNotifySignal())
+ QMetaObject::connect(object, p.notifySignalIndex(),
+ item, refreshIdx);
+
+
+ QMultiHash<QByteArray, QPair<QString, quint32> >::Iterator iter =
+ bindings.find(p.name());
+
+ while(iter != bindings.end() && iter.key() == p.name()) {
+ QmlPropertyViewItem *binding = new QmlPropertyViewItem(item);
+ binding->exprId = iter.value().second;
+ binding->setText(1, iter.value().first);
+ binding->setForeground(1, Qt::green);
+ ++iter;
+ }
+
+ item->setExpanded(true);
+ item->refresh();
+ }
+
+ for(QHash<QByteArray, QString>::ConstIterator iter = sigs.begin();
+ iter != sigs.end();
+ ++iter) {
+
+ QTreeWidgetItem *item = new QTreeWidgetItem(m_tree);
+ item->setText(0, iter.key());
+ item->setForeground(0, Qt::blue);
+ item->setText(1, iter.value());
+ }
+}
+
+void QmlPropertyView::refresh()
+{
+ setObject(m_object);
+}
+
+#include "qmlpropertyview.moc"
diff --git a/src/declarative/debugger/qmlpropertyview_p.h b/src/declarative/debugger/qmlpropertyview_p.h
new file mode 100644
index 0000000..469a08d
--- /dev/null
+++ b/src/declarative/debugger/qmlpropertyview_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROPERTYVIEW_P_H
+#define QMLPROPERTYVIEW_P_H
+
+#include <QtGui/qwidget.h>
+#include <QtCore/qpointer.h>
+#include <private/qmlwatches_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTreeWidget;
+class QTreeWidgetItem;
+class QmlPropertyView : public QWidget
+{
+ Q_OBJECT
+public:
+ QmlPropertyView(QmlWatches *watches, QWidget *parent = 0);
+
+ void setObject(QObject *);
+
+signals:
+ void objectClicked(quint32);
+
+public slots:
+ void refresh();
+ void itemDoubleClicked(QTreeWidgetItem *);
+ void itemClicked(QTreeWidgetItem *);
+
+private:
+ QPointer<QObject> m_object;
+ QTreeWidget *m_tree;
+ QmlWatches *m_watches;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLPROPERTYVIEW_P_H
+
diff --git a/src/declarative/debugger/qmlwatches.cpp b/src/declarative/debugger/qmlwatches.cpp
new file mode 100644
index 0000000..bac4cbd
--- /dev/null
+++ b/src/declarative/debugger/qmlwatches.cpp
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlwatches_p.h"
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qcolor.h>
+#include <QtDeclarative/qmlmetatype.h>
+#include <QtDeclarative/qmlexpression.h>
+
+QString QmlWatches::objectToString(QObject *obj)
+{
+ if(!obj)
+ return QLatin1String("NULL");
+
+ QString objectName = obj->objectName();
+ if(objectName.isEmpty())
+ objectName = QLatin1String("<unnamed>");
+
+ QString rv = QLatin1String(obj->metaObject()->className()) +
+ QLatin1String(": ") + objectName;
+
+ return rv;
+}
+
+class QmlWatchesProxy : public QObject
+{
+ Q_OBJECT
+public:
+ QmlWatchesProxy(QObject *object,
+ const QMetaProperty &prop,
+ int column,
+ QmlWatches *parent = 0);
+
+ QmlWatchesProxy(QmlExpressionObject *object,
+ int column,
+ QmlWatches *parent = 0);
+
+public slots:
+ void refresh();
+
+private:
+ QmlWatches *m_watches;
+ QObject *m_object;
+ QMetaProperty m_property;
+
+ QmlExpressionObject *m_expr;
+ int m_column;
+};
+
+QmlWatchesProxy::QmlWatchesProxy(QmlExpressionObject *object,
+ int column,
+ QmlWatches *parent)
+: QObject(parent), m_watches(parent), m_object(0), m_expr(object), m_column(column)
+{
+ QObject::connect(m_expr, SIGNAL(valueChanged()), this, SLOT(refresh()));
+}
+
+QmlWatchesProxy::QmlWatchesProxy(QObject *object,
+ const QMetaProperty &prop,
+ int column,
+ QmlWatches *parent)
+: QObject(parent), m_watches(parent), m_object(object), m_property(prop),
+ m_expr(0), m_column(column)
+{
+ static int refreshIdx = -1;
+ if(refreshIdx == -1)
+ refreshIdx = QmlWatchesProxy::staticMetaObject.indexOfMethod("refresh()");
+
+ QMetaObject::connect(m_object, prop.notifySignalIndex(),
+ this, refreshIdx);
+}
+
+void QmlWatchesProxy::refresh()
+{
+ QVariant v;
+ if(m_expr) v = m_expr->value();
+ else v= m_property.read(m_object);
+
+ m_watches->addValue(m_column, v);
+}
+
+QmlWatches::QmlWatches(QObject *parent)
+: QAbstractTableModel(parent), m_uniqueId(0)
+{
+}
+
+bool QmlWatches::hasWatch(quint32 objectId, const QByteArray &property)
+{
+ return m_watches.contains(qMakePair(objectId, property));
+}
+
+void QmlWatches::addWatch(QmlExpressionObject *expr)
+{
+ int oldColumn = columnCount(QModelIndex());
+
+ m_watches.append(qMakePair(quint32(0), QByteArray()));
+
+ beginInsertColumns(QModelIndex(), oldColumn, oldColumn);
+ endInsertColumns();
+
+ m_columnNames.append(expr->expression());
+
+ QmlWatchesProxy *proxy = new QmlWatchesProxy(expr, oldColumn, this);
+ m_proxies.append(proxy);
+
+ proxy->refresh();
+ m_values[m_values.count() - 1].first = true;
+}
+
+void QmlWatches::addWatch(quint32 objectId, const QByteArray &property)
+{
+ if(hasWatch(objectId, property))
+ return;
+
+ int oldColumn = columnCount(QModelIndex());
+
+ m_watches.append(qMakePair(objectId, property));
+
+ beginInsertColumns(QModelIndex(), oldColumn, oldColumn);
+ endInsertColumns();
+
+ QObject *obj = object(objectId);
+ m_columnNames.append(QLatin1String(property) + QLatin1String(" on ") + objectToString(obj));
+ QMetaProperty prop =
+ obj->metaObject()->property(obj->metaObject()->indexOfProperty(property.constData()));
+ QmlWatchesProxy *proxy = new QmlWatchesProxy(obj, prop, oldColumn, this);
+ m_proxies.append(proxy);
+ proxy->refresh();
+ m_values[m_values.count() - 1].first = true;
+}
+
+void QmlWatches::remWatch(quint32 objectId, const QByteArray &property)
+{
+ QPair<quint32, QByteArray> watch = qMakePair(objectId, property);
+ for(int ii = 0; ii < m_watches.count(); ++ii) {
+ if(m_watches.at(ii) == watch) {
+ m_watches.removeAt(ii);
+ m_columnNames.removeAt(ii);
+ if(m_proxies.at(ii))
+ delete m_proxies.at(ii);
+ m_proxies.removeAt(ii);
+
+
+ for(QList<Value>::Iterator iter = m_values.begin();
+ iter != m_values.end();
+ ) {
+ if(iter->column == ii) {
+ iter = m_values.erase(iter);
+ } else {
+ if(iter->column > ii)
+ --iter->column;
+ ++iter;
+ }
+ }
+ reset();
+ return;
+ }
+ }
+}
+
+quint32 QmlWatches::objectId(QObject *object)
+{
+ Q_ASSERT(object);
+
+ QHash<QObject *, QPair<QPointer<QObject>, quint32> *>::Iterator iter =
+ m_objects.find(object);
+ if(iter == m_objects.end()) {
+ iter = m_objects.insert(object, new QPair<QPointer<QObject>, quint32>(QPointer<QObject>(object), m_uniqueId++));
+ m_objectIds.insert(iter.value()->second, iter.value());
+ }
+
+ if(iter.value()->first != object) {
+ iter.value()->first = object;
+ iter.value()->second = m_uniqueId++;
+
+ m_objectIds.insert(iter.value()->second, iter.value());
+ }
+ return iter.value()->second;
+}
+
+QObject *QmlWatches::object(quint32 id)
+{
+ QHash<quint32, QPair<QPointer<QObject>, quint32> *>::Iterator iter =
+ m_objectIds.find(id);
+ if(iter == m_objectIds.end())
+ return 0;
+
+ if(!iter.value()->first) {
+ m_objectIds.erase(iter);
+ return 0;
+ }
+
+ return iter.value()->first;
+}
+
+void QmlWatches::addValue(int column, const QVariant &value)
+{
+ int row = m_values.count();
+
+ beginInsertRows(QModelIndex(), row, row);
+ Value v;
+ v.column = column;
+ v.variant = value;
+ v.first = false;
+ m_values.append(v);
+ endInsertRows();
+}
+
+int QmlWatches::columnCount(const QModelIndex &) const
+{
+ return m_watches.count();
+}
+
+int QmlWatches::rowCount(const QModelIndex &) const
+{
+ return m_values.count();
+}
+
+QVariant QmlWatches::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal && section < m_columnNames.count() &&
+ role == Qt::DisplayRole)
+ return m_columnNames.at(section);
+ else
+ return QVariant();
+}
+
+QVariant QmlWatches::data(const QModelIndex &idx, int role) const
+{
+ if(m_values.at(idx.row()).column == idx.column()) {
+ if(role == Qt::DisplayRole) {
+ const QVariant &value = m_values.at(idx.row()).variant;
+
+ QString str = value.toString();
+
+ if(str.isEmpty() && QmlMetaType::isObject(value.userType())) {
+ QObject *o = QmlMetaType::toQObject(value);
+ if(o) {
+ QString objectName = o->objectName();
+ if(objectName.isEmpty())
+ objectName = QLatin1String("<unnamed>");
+ str = QLatin1String(o->metaObject()->className()) +
+ QLatin1String(": ") + objectName;
+ }
+ }
+
+ if(str.isEmpty()) {
+ QDebug d(&str);
+ d << value;
+ }
+ return QVariant(str);
+ } else if(role == Qt::BackgroundRole) {
+ if(m_values.at(idx.row()).first)
+ return QColor(Qt::green);
+ else
+ return QVariant();
+ } else {
+ return QVariant();
+ }
+ } else {
+ return QVariant();
+ }
+}
+
+#include "qmlwatches.moc"
diff --git a/src/declarative/debugger/qmlwatches_p.h b/src/declarative/debugger/qmlwatches_p.h
new file mode 100644
index 0000000..6c383a1
--- /dev/null
+++ b/src/declarative/debugger/qmlwatches_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLWATCHES_P_H
+#define QMLWATCHES_P_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qset.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qabstractitemmodel.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlWatchesProxy;
+class QmlExpressionObject;
+
+class QmlWatches : public QAbstractTableModel
+{
+ Q_OBJECT
+public:
+ QmlWatches(QObject *parent = 0);
+
+ bool hasWatch(quint32 objectId, const QByteArray &property);
+ void addWatch(quint32 objectId, const QByteArray &property);
+ void remWatch(quint32 objectId, const QByteArray &property);
+
+ void addWatch(QmlExpressionObject *);
+
+ quint32 objectId(QObject *);
+ QObject *object(quint32);
+
+ static QString objectToString(QObject *obj);
+protected:
+ int columnCount(const QModelIndex &) const;
+ int rowCount(const QModelIndex &) const;
+ QVariant data(const QModelIndex &, int) const;
+ QVariant headerData(int, Qt::Orientation, int) const;
+
+private:
+ friend class QmlWatchesProxy;
+ QList<QPair<quint32, QByteArray> > m_watches;
+
+ void addValue(int, const QVariant &);
+ struct Value {
+ int column;
+ QVariant variant;
+ bool first;
+ };
+ QList<Value> m_values;
+ QStringList m_columnNames;
+ QList<QPointer<QmlWatchesProxy> > m_proxies;
+
+ quint32 m_uniqueId;
+ QHash<QObject *, QPair<QPointer<QObject>, quint32> *> m_objects;
+ QHash<quint32, QPair<QPointer<QObject>, quint32> *> m_objectIds;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLWATCHES_P_H
diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro
new file mode 100644
index 0000000..fac7c08
--- /dev/null
+++ b/src/declarative/declarative.pro
@@ -0,0 +1,30 @@
+TARGET = QtDeclarative
+QPRO_PWD = $$PWD
+QT = core gui xml script network
+contains(QT_CONFIG, svg): QT += svg
+DEFINES += QT_BUILD_DECLARATIVE_LIB
+DEFINES += QT_NO_USING_NAMESPACE
+win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x66000000
+solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
+
+LIBS += -lgcov
+
+unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui QtXml
+
+QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage
+
+include(../qbase.pri)
+
+#modules
+include(3rdparty/3rdparty.pri)
+include(util/util.pri)
+include(fx/fx.pri)
+include(canvas/canvas.pri)
+include(qml/qml.pri)
+include(timeline/timeline.pri)
+include(extra/extra.pri)
+include(widgets/widgets.pri)
+include(test/test.pri)
+include(debugger/debugger.pri)
+
+contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, opengles1):include(opengl/opengl.pri)
diff --git a/src/declarative/extra/extra.pri b/src/declarative/extra/extra.pri
new file mode 100644
index 0000000..83978f1
--- /dev/null
+++ b/src/declarative/extra/extra.pri
@@ -0,0 +1,24 @@
+SOURCES += \
+ extra/qnumberformat.cpp \
+ extra/qmlnumberformatter.cpp \
+ extra/qfxintegermodel.cpp
+
+HEADERS += \
+ extra/qnumberformat.h \
+ extra/qmlnumberformatter.h \
+ extra/qfxintegermodel.h
+
+contains(QT_CONFIG, xmlpatterns) {
+ QT+=xmlpatterns
+ SOURCES += extra/qmlxmllistmodel.cpp
+ HEADERS += extra/qmlxmllistmodel.h
+}
+
+# SQL is permanently enabled :-/
+#contains(QT_CONFIG, sql) {
+ QT+= sql
+ SOURCES += extra/qmlsqlquery.cpp \
+ extra/qmlsqlconnection.cpp
+ HEADERS += extra/qmlsqlquery.h \
+ extra/qmlsqlconnection.h
+#}
diff --git a/src/declarative/extra/qfxintegermodel.cpp b/src/declarative/extra/qfxintegermodel.cpp
new file mode 100644
index 0000000..3c4d0d9
--- /dev/null
+++ b/src/declarative/extra/qfxintegermodel.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxintegermodel.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxIntegerModel, IntegerModel);
+
+class QFxIntegerModelPrivate
+{
+public:
+ QFxIntegerModelPrivate() : min(0), max(0) {}
+ int min;
+ int max;
+};
+
+QFxIntegerModel::QFxIntegerModel(QObject *parent)
+ : QListModelInterface(parent)
+{
+ d = new QFxIntegerModelPrivate;
+}
+
+QFxIntegerModel::~QFxIntegerModel()
+{
+ delete d;
+}
+
+int QFxIntegerModel::minimum() const
+{
+ return d->min;
+}
+
+void QFxIntegerModel::setMinimum(int min)
+{
+ d->min = min;
+}
+
+int QFxIntegerModel::maximum() const
+{
+ return d->max;
+}
+
+void QFxIntegerModel::setMaximum(int max)
+{
+ d->max = max;
+}
+
+int QFxIntegerModel::count() const
+{
+ return qMax(0, d->max - d->min + 1);
+}
+
+QHash<int,QVariant> QFxIntegerModel::data(int index, const QList<int> &roles) const
+{
+ QHash<int,QVariant> returnHash;
+
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ QVariant info;
+ switch(role) {
+ case Qt::DisplayRole:
+ info = QVariant(QString::number(d->min+index));
+ break;
+ default:
+ break;
+ }
+ returnHash.insert(role, info);
+ }
+ return returnHash;
+}
+
+QString QFxIntegerModel::toString(int role) const
+{
+ switch(role) {
+ case Qt::DisplayRole:
+ return QLatin1String("display");
+ default:
+ return QLatin1String("");
+ }
+}
+
+QList<int> QFxIntegerModel::roles() const
+{
+ return QList<int>() << Qt::DisplayRole;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/extra/qfxintegermodel.h b/src/declarative/extra/qfxintegermodel.h
new file mode 100644
index 0000000..3a48a56
--- /dev/null
+++ b/src/declarative/extra/qfxintegermodel.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXINTMODEL_H
+#define QFXINTMODEL_H
+
+#include <QObject>
+#include "qml.h"
+#include <qlistmodelinterface.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxIntegerModelPrivate;
+class Q_DECLARATIVE_EXPORT QFxIntegerModel : public QListModelInterface
+{
+ Q_OBJECT
+public:
+ QFxIntegerModel(QObject *parent=0);
+ ~QFxIntegerModel();
+
+ Q_PROPERTY(int minimum READ minimum WRITE setMinimum);
+ int minimum() const;
+ void setMinimum(int);
+
+ Q_PROPERTY(int maximum READ maximum WRITE setMaximum);
+ int maximum() const;
+ void setMaximum(int);
+
+ int count() const;
+ QHash<int, QVariant> data(int index, const QList<int> &roles) const;
+ QList<int> roles() const;
+ QString toString(int role) const;
+
+private:
+ QFxIntegerModelPrivate *d;
+};
+
+QML_DECLARE_TYPE(QFxIntegerModel);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/extra/qmlnumberformatter.cpp b/src/declarative/extra/qmlnumberformatter.cpp
new file mode 100644
index 0000000..1549525
--- /dev/null
+++ b/src/declarative/extra/qmlnumberformatter.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlnumberformatter.h"
+#include "private/qobject_p.h"
+
+
+QT_BEGIN_NAMESPACE
+//TODO: set locale
+// docs
+// this is a wrapper around qnumberformat (test integration)
+// if number or format haven't been explictly set, text should be an empty string
+
+class QmlNumberFormatterPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlNumberFormatter)
+public:
+ QmlNumberFormatterPrivate() : locale(QLocale::system()), number(0), classComplete(true) {}
+
+ void updateText();
+
+ QLocale locale;
+ QString format;
+ QNumberFormat numberFormat;
+ QString text;
+ qreal number;
+ bool classComplete;
+};
+/*!
+ \qmlclass NumberFormatter
+ \brief The NumberFormatter allows you to control the format of a number string.
+
+ The format property documentation has more details on how the format can be manipulated.
+
+ In the following example, the text element will display the text "1,234.57".
+ \code
+ NumberFormatter { id: Formatter; number: 1234.5678; format: "##,##0.##" }
+ Text { text: Formatter.text }
+ \endcode
+
+ */
+/*!
+ \internal
+ \class QmlNumberFormatter
+ \ingroup group_utility
+ \brief The QmlNumberFormatter class allows you to format a number to a particular string format/locale specific number format.
+*/
+
+QmlNumberFormatter::QmlNumberFormatter(QObject *parent)
+: QObject(*(new QmlNumberFormatterPrivate), parent)
+{
+}
+
+QmlNumberFormatter::~QmlNumberFormatter()
+{
+}
+
+/*!
+ \qmlproperty string NumberFormatter::text
+
+ The number in the specified format.
+ <br>
+ If no format is specified the text will be empty.
+*/
+
+QString QmlNumberFormatter::text() const
+{
+ Q_D(const QmlNumberFormatter);
+ return d->text;
+}
+
+/*!
+ \qmlproperty qreal NumberFormatter::number
+
+ A single point precision number. (Doubles are not yet supported)
+
+*/
+qreal QmlNumberFormatter::number() const
+{
+ Q_D(const QmlNumberFormatter);
+ return d->number;
+}
+
+/*!
+ \qmlproperty string NumberFormatter::format
+
+ The particular format the number will adhere to during the conversion to text.
+ <br>
+ The format syntax follows a style similar to the Unicode Standard (UTS35).
+
+ The table below shows the characters, patterns that can be used in the format.
+
+ <table border="0" align="center">
+ <tr style="background-color: #D6E2E8"><th> Character </th><th> Meaning </th></tr>
+ <tr><td> # </td><td> Any digit(s), zero shows as absent (for leading/trailing zeroes) </td></tr>
+ <tr><td> 0 </td><td> Implicit digit. Zero will show in the case that the input number is too small.</td></tr>
+ <tr><td> . </td><td> Decimal separator. Output decimal seperator will be dependant on system locale.</td></tr>
+ <tr><td> , </td><td> Grouping separator. The number of digits (either #, or 0) between the grouping separator and the decimal (or the rightmost digit) will determine the groupingSize)</td></tr>
+ <tr><td> other </td><td> Any other character will be taken as a string literal and placed directly into the output string </td></tr>
+ </table>
+
+ Invalid formats will not guarantee a meaningful text output.<br>
+
+ \note <i>Input numbers that are too long for the given format will be rounded dependent on precison based on the position of the decimal point </i>
+
+ The following table illustrates the output text created by applying some examples of numeric formats to the formatter.
+
+ <table border="0" align="center">
+ <tr style="background-color: #D6E2E8"><th> Format </th><th> Number </th><th> Output </th></tr>
+ <tr><td> ### </td><td> 123456 </td><td> 123456 </td></tr>
+ <tr><td> 000 </td><td> 123456 </td><td> 123456 </td></tr>
+ <tr><td> ###### </td><td> 1234 </td><td> 1234 </td></tr>
+ <tr><td> 000000 </td><td> 1234 </td><td> 001234 </td></tr>
+ <tr><td> ##,##0.## </td><td> 1234.456 </td><td> 1,234.46 (for US locale)<br> 1 234,46 (for FR locale)</td></tr>
+ <tr><td> 000000,000.# </td><td> 123456 </td><td> 000,123,456 (for US locale)<br> 000 123 456 (for FR locale)</td></tr>
+ <tr><td> 0.0### </td><td> 0.999997 </td><td> 1.0 </td></tr>
+ <tr><td> (000) 000 - 000 </td><td> 12345678 </td><td> (012) 345 - 678 </td></tr>
+ <tr><td> #A</td><td>12</td><td>12A</td></tr>
+ </table>
+
+*/
+QString QmlNumberFormatter::format() const
+{
+ Q_D(const QmlNumberFormatter);
+ return d->format;
+}
+
+void QmlNumberFormatter::setNumber(const qreal &number)
+{
+ Q_D(QmlNumberFormatter);
+ if (d->number == number)
+ return;
+ d->number = number;
+ d->updateText();
+}
+
+void QmlNumberFormatter::setFormat(const QString &format)
+{
+ Q_D(QmlNumberFormatter);
+ //no format checking
+ if (format.isEmpty())
+ d->format = QString::null;
+ else
+ d->format = format;
+ d->updateText();
+}
+
+void QmlNumberFormatterPrivate::updateText()
+{
+ Q_Q(QmlNumberFormatter);
+ if (!classComplete)
+ return;
+
+ QNumberFormat tempFormat;
+ tempFormat.setFormat(format);
+ tempFormat.setNumber(number);
+
+ text = tempFormat.text();
+
+ emit q->textChanged();
+}
+
+void QmlNumberFormatter::classBegin()
+{
+ Q_D(QmlNumberFormatter);
+ d->classComplete = false;
+}
+
+void QmlNumberFormatter::classComplete()
+{
+ Q_D(QmlNumberFormatter);
+ d->classComplete = true;
+ d->updateText();
+}
+
+QML_DEFINE_TYPE(QmlNumberFormatter, NumberFormatter);
+QT_END_NAMESPACE
diff --git a/src/declarative/extra/qmlnumberformatter.h b/src/declarative/extra/qmlnumberformatter.h
new file mode 100644
index 0000000..e053be5
--- /dev/null
+++ b/src/declarative/extra/qmlnumberformatter.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLNUMBERFORMATTER_H
+#define QMLNUMBERFORMATTER_H
+
+#include <qml.h>
+#include "qnumberformat.h"
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlNumberFormatterPrivate;
+class Q_DECLARATIVE_EXPORT QmlNumberFormatter : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString text READ text NOTIFY textChanged)
+ Q_PROPERTY(QString format READ format WRITE setFormat)
+ Q_PROPERTY(qreal number READ number WRITE setNumber)
+public:
+ QmlNumberFormatter(QObject *parent=0);
+ ~QmlNumberFormatter();
+
+ QString text() const;
+
+ qreal number() const;
+ void setNumber(const qreal &);
+
+ QString format() const;
+ void setFormat(const QString &);
+
+ virtual void classBegin();
+ virtual void classComplete();
+
+Q_SIGNALS:
+ void textChanged();
+
+private:
+ Q_DISABLE_COPY(QmlNumberFormatter)
+ Q_DECLARE_PRIVATE(QmlNumberFormatter)
+};
+
+QML_DECLARE_TYPE(QmlNumberFormatter);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/extra/qmlsqlconnection.cpp b/src/declarative/extra/qmlsqlconnection.cpp
new file mode 100644
index 0000000..25ab033
--- /dev/null
+++ b/src/declarative/extra/qmlsqlconnection.cpp
@@ -0,0 +1,437 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlsqlconnection.h"
+#include "private/qobject_p.h"
+
+#include <QSqlError>
+#include <QSqlDriver>
+#include <QDebug>
+
+#include <qml.h>
+#include <qmlcontext.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(QmlSqlConnection, SqlConnection);
+
+class QmlSqlConnectionPrivate: public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlSqlConnection)
+public:
+ QmlSqlConnectionPrivate() : port(0) {}
+
+ int port;
+ QString name, databaseName, connectionOptions;
+ QString hostName, userName, password, driver;
+};
+
+/*!
+ \qmlclass SqlConnection QmlSqlConnection
+ \brief The SqlConnection element describes a connection to an SQL database.
+
+ The SqlConnection element works in a similar way to
+ QSqlDatabase::addDatabase(). It allows setting the database properties
+ such that the connection does not need to be set up in C++ code.
+ It differs from QSqlDatabase::addDatabase() in that it will automatically
+ open the database.
+
+ The database can then either be used from an SqlQuery element using its id
+ as a bind, or using its name. If the database is set up externally to
+ Qml the query should connect using its name.
+
+ \qml
+ SqlConnection {
+ id: myConnection
+ name: "qmlConnection"
+ driver: "QSQLITE"
+ databaseName: "mydb.sqlite"
+ }
+ SqlQuery { id: listmodel; connection: myConnection; query: "SELECT * FROM mytable" }
+ SqlQuery { id: othermodel; connection: "qmlConnection"; query: "SELECT * FROM myothertable" }
+ \endqml
+*/
+
+/*!
+ \qmlproperty QString SqlConnection::name
+ \default
+
+ Defines the connection's name. The name allows the connection to be
+ retrieved using the connection property of SqlQuery or when
+ QSqlDatabase::database()
+*/
+
+/*!
+ \qmlproperty list<string> SqlConnection::tables
+
+ Defines the set of tables that exist in the database for the connection.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::databaseName
+
+ Defines the connection's database name. This is used when opening the
+ connection to the database.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::driver
+
+ Defines the driver type of the connection. This is used when opening the
+ connection to the database.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::connectOptions
+
+ Defines the options used when connecting to the database. These are used
+ when opening the connection to the database.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::hostName
+
+ Defines the connection's host name. This is used when opening the
+ connection to the database.
+*/
+
+/*!
+ \qmlproperty int SqlConnection::port
+
+ Defines the connection's port number. This is used when opening the
+ connection to the database.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::userName
+
+ Defines the connection's user name. This is used when opening the
+ connection to the database.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::password
+
+ Defines the connection's password. This is used when opening the
+ connection to the database.
+*/
+
+/*!
+ \qmlproperty string SqlConnection::lastError
+
+ Defines the last error, if one occurred, when working with the database.
+ If the error occurred in conjunction with an SQL query the error will be
+ defined by SqlQuery::lastError.
+*/
+
+/*!
+ \internal
+ \class QmlSqlConnection
+ \brief The QmlSqlConnection class manages a connection to an SQL database.
+*/
+
+/*!
+ Constructs a QmlSqlConnection with the given \a parent.
+*/
+QmlSqlConnection::QmlSqlConnection(QObject *parent)
+: QObject(*(new QmlSqlConnectionPrivate), parent)
+{
+}
+
+/*!
+ Destroys the QmlSqlConnection.
+*/
+QmlSqlConnection::~QmlSqlConnection()
+{
+ QSqlDatabase db = database();
+ if (db.isOpen())
+ db.close();
+}
+
+/*!
+ Returns the connection's name.
+ This is equivalent to QSqlDatabase::connectionName().
+ \sa setName()
+*/
+QString QmlSqlConnection::name() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->name;
+}
+
+/*!
+ Returns the connection's database name.
+ This is equivalent to QSqlDatabase::databaseName().
+ \sa setDatabaseName()
+*/
+QString QmlSqlConnection::databaseName() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->databaseName;
+}
+
+/*!
+ Returns the connect options string used for this connection.
+
+ \sa setConnectOptions()
+*/
+QString QmlSqlConnection::connectOptions() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->connectionOptions;
+}
+
+/*!
+ Returns the connection's host name.
+ \sa setHostName()
+*/
+QString QmlSqlConnection::hostName() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->hostName;
+}
+
+/*!
+ Returns the connection's port number. The value is undefined if the port
+ number has not been set.
+
+ \sa setPort()
+*/
+int QmlSqlConnection::port() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->port;
+}
+
+/*!
+ Returns the connection's user name.
+
+ \sa setUserName()
+*/
+QString QmlSqlConnection::userName() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->userName;
+}
+
+/*!
+ Returns the connection's password.
+
+ \sa setPassword)()
+*/
+QString QmlSqlConnection::password() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->password;
+}
+
+/*!
+ Returns the connection's driver name.
+
+ \sa setDriver()
+*/
+QString QmlSqlConnection::driver() const
+{
+ Q_D(const QmlSqlConnection);
+ return d->driver;
+}
+
+/*!
+ Returns a list of the database's tables.
+*/
+QStringList QmlSqlConnection::tables() const
+{
+ return database().tables();
+}
+
+/*!
+ Sets the connection's name to the given \a name.
+
+ \sa name()
+*/
+void QmlSqlConnection::setName(const QString &name)
+{
+ Q_D(QmlSqlConnection);
+ d->name = name;
+}
+
+/*!
+ Set's the connection's database name to the given \a name.
+
+ \sa databaseName()
+*/
+void QmlSqlConnection::setDatabaseName(const QString &name)
+{
+ Q_D(QmlSqlConnection);
+ d->databaseName = name;
+}
+
+/*!
+ Sets the connection's options to the given \a options.
+
+ \sa connectOptions(), QSqlDatabase::setConnectOptions()
+*/
+void QmlSqlConnection::setConnectOptions(const QString &options)
+{
+ Q_D(QmlSqlConnection);
+ d->connectionOptions = options;
+}
+
+/*!
+ Sets the connection's host name to the given \a name.
+
+ \sa hostName()
+*/
+void QmlSqlConnection::setHostName(const QString &name)
+{
+ Q_D(QmlSqlConnection);
+ d->hostName = name;
+}
+
+/*!
+ Sets the connection's port number to the given \a port.
+
+ \sa port()
+*/
+void QmlSqlConnection::setPort(int port)
+{
+ Q_D(QmlSqlConnection);
+ d->port = port;
+}
+
+/*!
+ Sets the connection's user name to the given \a name.
+
+ \sa userName()
+*/
+void QmlSqlConnection::setUserName(const QString &name)
+{
+ Q_D(QmlSqlConnection);
+ d->userName = name;
+}
+
+/*!
+ Sets the connection's password to the given \a password.
+
+ \sa password()
+*/
+void QmlSqlConnection::setPassword(const QString &password)
+{
+ Q_D(QmlSqlConnection);
+ d->password = password;
+}
+
+/*!
+ Returns information about the last error that occurred on the database.
+
+ Failures that occur in conjunction with an individual query are
+ reported by QmlSqlQuery::lastError()
+*/
+QString QmlSqlConnection::lastError() const
+{
+ return database().lastError().text();
+}
+
+/*!
+ Sets the connection's driver to the specified driver \a type.
+
+ \sa driver(), QSqlDatabase::addDatabase()
+*/
+void QmlSqlConnection::setDriver(const QString &type)
+{
+ Q_D(QmlSqlConnection);
+ d->driver = type;
+}
+
+/*!
+ \reimp
+*/
+void QmlSqlConnection::classComplete()
+{
+}
+
+/*!
+ Returns the database object associated with this connection.
+ If the database is not yet open, it will open the database
+ passed on the settings specified for the SQL connection.
+*/
+QSqlDatabase QmlSqlConnection::database() const
+{
+ Q_D(const QmlSqlConnection);
+
+ QSqlDatabase db;
+ if (QSqlDatabase::connectionNames().contains(d->name)) {
+ db = QSqlDatabase::database(d->name);
+ } else {
+ db = QSqlDatabase::addDatabase(
+ d->driver.isEmpty()
+ ? QLatin1String("QSQLITE")
+ : d->driver,
+ d->name.isEmpty()
+ ? QLatin1String(QSqlDatabase::defaultConnection)
+ : d->name);
+ }
+ if (db.isOpen())
+ return db;
+ if ((d->driver.isEmpty() || d->driver == QLatin1String("QSQLITE")) &&
+ qmlContext(this)) {
+ // SQLITE uses files for databases, hence use relative pathing
+ // if possible.
+ QUrl url = qmlContext(this)->resolvedUrl(d->databaseName);
+ if (url.isRelative() || url.scheme() == QLatin1String("file"))
+ db.setDatabaseName(url.toLocalFile());
+ else
+ db.setDatabaseName(d->databaseName);
+ } else {
+ db.setDatabaseName(d->databaseName);
+ }
+ db.setConnectOptions(d->connectionOptions);
+ db.setHostName(d->hostName);
+ db.setPassword(d->password);
+ db.setPort(d->port);
+ db.setUserName(d->userName);
+ if (!db.open())
+ qWarning() << "Failed to open database" << lastError();
+
+ return db;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/extra/qmlsqlconnection.h b/src/declarative/extra/qmlsqlconnection.h
new file mode 100644
index 0000000..2cc5774
--- /dev/null
+++ b/src/declarative/extra/qmlsqlconnection.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSQLCONNECTION_H
+#define QMLSQLCONNECTION_H
+
+#include <qml.h>
+#include <QSqlDatabase>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QSqlDatabase;
+class QmlSqlConnectionPrivate;
+class Q_DECLARATIVE_EXPORT QmlSqlConnection : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString name READ name WRITE setName);
+ Q_PROPERTY(QStringList tables READ tables);
+ Q_PROPERTY(QString databaseName READ databaseName WRITE setDatabaseName);
+ Q_PROPERTY(QString driver READ driver WRITE setDriver);
+ Q_PROPERTY(QString connectOptions READ connectOptions WRITE setConnectOptions);
+ Q_PROPERTY(QString hostName READ hostName WRITE setHostName);
+ Q_PROPERTY(int port READ port WRITE setPort);
+ Q_PROPERTY(QString userName READ userName WRITE setUserName);
+ Q_PROPERTY(QString password READ password WRITE setPassword);
+ Q_PROPERTY(QString lastError READ lastError);
+ Q_CLASSINFO("DefaultProperty", "name")
+public:
+ QmlSqlConnection(QObject *parent = 0);
+ ~QmlSqlConnection();
+
+ QString name() const;
+ void setName(const QString &);
+
+ QStringList tables() const;
+
+ QString databaseName() const;
+ void setDatabaseName(const QString &);
+
+ QString connectOptions() const;
+ void setConnectOptions(const QString &);
+
+ QString hostName() const;
+ void setHostName(const QString &);
+
+ int port() const;
+ void setPort(int);
+
+ QString userName() const;
+ void setUserName(const QString &);
+
+ QString password() const;
+ void setPassword(const QString &);
+
+ QString driver() const;
+ void setDriver(const QString &);
+
+ QString lastError() const;
+
+ virtual void classComplete();
+
+ QSqlDatabase database() const;
+private:
+ Q_DISABLE_COPY(QmlSqlConnection)
+ Q_DECLARE_PRIVATE(QmlSqlConnection)
+};
+
+QML_DECLARE_TYPE(QmlSqlConnection);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QMLXMLLISTMODEL_H
+
diff --git a/src/declarative/extra/qmlsqlquery.cpp b/src/declarative/extra/qmlsqlquery.cpp
new file mode 100644
index 0000000..5bd1459
--- /dev/null
+++ b/src/declarative/extra/qmlsqlquery.cpp
@@ -0,0 +1,694 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlsqlquery.h"
+#include "qmlsqlconnection.h"
+#include "private/qobject_p.h"
+
+#include <QDebug>
+#include <QSqlQuery>
+#include <QSqlError>
+#include <QSqlField>
+#include <QSqlRecord>
+#include <QSqlDatabase>
+#include <QSqlDriver>
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QmlSqlBind, SqlBind);
+QML_DEFINE_TYPE(QmlSqlQuery, SqlQuery);
+
+class QmlSqlBindPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlSqlBind)
+public:
+ QmlSqlBindPrivate() {}
+
+ QString name;
+ QVariant value;
+};
+
+/*!
+ \qmlclass SqlBind QmlSqlBind
+ \brief The SqlBind element specifies a value binding for an SqlQuery element.
+
+ By using bindings its possible to cause a SqlQuery to update itself
+ when values bound through the SqlBind change. Hence in the example
+ below the results for the SqlQuery will change as searchText changes.
+
+ If the query is not a SELECT statement, the effects of the bound
+ values will only apply when the SqlQuery exec() slot is called.
+
+ \qml
+ SqlQuery {
+ query: "SELECT * FROM mytable WHERE name LIKE :value"
+ bindings: SqlBind {
+ name: ":value"
+ value: searchText + '%'
+ }
+ }
+ SqlQuery {
+ query: "SELECT * FROM mytable WHERE type = ?"
+ bindings: SqlBind {
+ value: "simple"
+ }
+ }
+ \endqml
+*/
+
+/*!
+ \internal
+ \class QmlSqlBind
+ \brief The QmlSqlBind class specifies a value binding for a QmlSqlQuery.
+*/
+
+/*!
+ \fn void QmlSqlBind::valueChanged()
+
+ This signal is emitted when the value property of the SqlBind changes.
+*/
+
+/*!
+ \qmlproperty QString SqlBind::name
+
+ Defines the placeholder name of the bind. If no name is specified the
+ bind will use its position within the SqlQuery's bindings to bind
+ into the query.
+*/
+
+/*!
+ \qmlproperty QVariant SqlBind::value
+
+ Defines the value to bind into the query.
+*/
+
+/*!
+ Constructs a QmlSqlVind with the given \a parent
+*/
+QmlSqlBind::QmlSqlBind(QObject *parent)
+: QObject(*(new QmlSqlBindPrivate()), parent)
+{
+}
+
+/*!
+ Destroys the QmlSqlBind.
+*/
+QmlSqlBind::~QmlSqlBind()
+{
+}
+
+/*!
+ Returns the binding's name.
+
+ \sa setName()
+*/
+QString QmlSqlBind::name() const
+{
+ Q_D(const QmlSqlBind);
+ return d->name;
+}
+
+/*!
+ Returns the binding's value.
+
+ \sa setValue()
+*/
+QVariant QmlSqlBind::value() const
+{
+ Q_D(const QmlSqlBind);
+ return d->value;
+}
+
+/*!
+ Sets the binding's name to the given \a name.
+
+ \sa name()
+*/
+void QmlSqlBind::setName(const QString &name)
+{
+ Q_D(QmlSqlBind);
+ d->name = name;
+}
+
+/*!
+ Sets the binding's value to the given \a value.
+
+ \sa value()
+*/
+void QmlSqlBind::setValue(const QVariant &value)
+{
+ Q_D(QmlSqlBind);
+ if (d->value != value) {
+ d->value = value;
+ emit valueChanged();
+ }
+}
+
+/*!
+ \reimp
+*/
+void QmlSqlBind::classComplete()
+{
+}
+
+class QmlSqlQueryPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlSqlQuery)
+public:
+ QmlSqlQueryPrivate(QmlSqlQuery *owner) : isSel(false), query(NULL), requireCache(false), count(-1), binds(owner) {}
+ void prepareQuery() const;
+ void bindQuery() const;
+ void cacheQuery() const;
+ void grabRoles() const;
+
+ QString queryText;
+ bool isSel;
+ QVariant connectionVariant;
+ mutable QSqlQuery *query;
+ mutable bool requireCache;
+ mutable int count;
+ mutable QList<int> roles;
+ mutable QStringList roleNames;
+ mutable QVector< QVector< QVariant > > cache;
+
+ class QmlSqlBindList : public QmlList<QmlSqlBind *>
+ {
+ public:
+ QmlSqlBindList(QmlSqlQuery *owner)
+ : q(owner){}
+
+ void append(QmlSqlBind *o) {
+ m_contents.append(o);
+ QObject::connect(o, SIGNAL(valueChanged()), q, SLOT(resetBinds()));
+ }
+ void clear() { m_contents.clear(); }
+ int count() const { return m_contents.count(); }
+ void removeAt(int pos) { return m_contents.removeAt(pos); }
+ QmlSqlBind *at(int pos) const { return m_contents.at(pos); }
+ void insert(int pos, QmlSqlBind *o) { m_contents.insert(pos, o); }
+ private:
+ QList<QmlSqlBind *> m_contents;
+ QmlSqlQuery *q;
+ };
+
+ QmlSqlBindList binds;
+};
+
+/*!
+ \qmlclass SqlQuery QmlSqlQuery
+ \brief The SqlQuery element describes a query into an SQL database.
+
+ The SqlQuery element has three parts. The first is the query itself,
+ which can either be specified using the query property or by the
+ default text for the element. The second specifies the connection
+ to the database. This can either be a bound id from an SqlConnection
+ or the connections name. If the connection is specified in a QML
+ SqlConnection it is recommend to bind to the id to help ensure the
+ database is complete before attempting to attach to it. If no
+ connectoin is specified the default connection is used.
+
+ It is also possible to bind values into the query using the bindings
+ property. See SqlBind for more information on how to bind values into
+ the query.
+
+ If the query is a select statement it can be used as a model for a ListView.
+ The roles will be the columns of the result set. Use the SQL AS keyword
+ in the query if you want to override the column names from that of the
+ table selected. You should also use the AS keyword if there is no
+ appropriate table column name for the result column.
+
+ \qml
+ SqlQuery { connection: qmlConnectionId; query: "DELETE FROM mytable" }
+ SqlQuery {
+ connection: "connectionName"
+ query: "SELECT * FROM mytable"
+ }
+ SqlQuery { query: "SELECT id AS recordId, (firstName || ' ' || lastName) AS fullName FROM mytable" }
+ \endqml
+*/
+
+/*
+ \class QmlSqlQuery
+ \brief the QmlSqlQuery class manages a query into an SQL database.
+*/
+
+/*!
+ \qmlproperty QString SqlQuery::query
+ \default
+
+ Defines the query text.
+*/
+
+/*!
+ \qmlproperty QVariant SqlQuery::connection
+
+ Defines the connection to an SQL database used by the query.
+*/
+
+/*!
+ \qmlproperty QString SqlQuery::lastError
+
+ Defines the last error, if one occurred, when working with the query.
+*/
+
+/*!
+ \qmlproperty list<SqlBind> SqlQuery::bindings
+
+ The bindings property contains the list of values to bind into the
+ query. See SqlBind for more information.
+*/
+
+/*!
+ Constructs a QmlSqlQuery with the given \a parent.
+*/
+QmlSqlQuery::QmlSqlQuery(QObject *parent)
+: QListModelInterface(*(new QmlSqlQueryPrivate(this)), parent)
+{
+}
+
+/*!
+ Destroys the QmlSqlQuery.
+*/
+QmlSqlQuery::~QmlSqlQuery()
+{
+ Q_D(QmlSqlQuery);
+ if (d->query)
+ delete d->query;
+}
+
+/*!
+ Returns the query's bound variables.
+*/
+QmlList<QmlSqlBind *> *QmlSqlQuery::bindings()
+{
+ Q_D(QmlSqlQuery);
+ return &d->binds;
+}
+
+/*!
+ Returns the query's bound variables.
+*/
+const QmlList<QmlSqlBind *> *QmlSqlQuery::bindings() const
+{
+ Q_D(const QmlSqlQuery);
+ return &d->binds;
+}
+
+/*!
+ Returns the query text.
+
+ \sa setQuery()
+*/
+QString QmlSqlQuery::query() const
+{
+ Q_D(const QmlSqlQuery);
+ return d->queryText;
+}
+
+/*!
+ Sets the query text to the given \a text.
+*/
+void QmlSqlQuery::setQuery(const QString &text)
+{
+ Q_D(QmlSqlQuery);
+ if (text != d->queryText) {
+ d->queryText = text;
+
+ static const QLatin1String select("select");
+ d-> isSel = text.trimmed().indexOf(select, 0, Qt::CaseInsensitive) == 0;
+
+ if (d->query)
+ resetQuery();
+ }
+}
+
+/*!
+ Returns the query's connection specifier.
+
+ \sa setConnection()
+*/
+QVariant QmlSqlQuery::connection() const
+{
+ Q_D(const QmlSqlQuery);
+ return d->connectionVariant;
+}
+
+/*!
+ Sets the query's connection specifier.
+
+ \sa connection()
+*/
+void QmlSqlQuery::setConnection(const QVariant &connection)
+{
+ Q_D(QmlSqlQuery);
+ if (connection != d->connectionVariant) {
+ d->connectionVariant = connection;
+ if (d->query)
+ resetQuery();
+ else if (d->count == 0) // data has been requested
+ d->prepareQuery();
+ }
+}
+
+/*!
+ Returns the set of values for a given set of requested \a roles for the
+ specified \a row of the query result set. Returns an empty hash if the
+ query is not a select statement.
+
+ \sa count(), roles(), toString()
+*/
+QHash<int,QVariant> QmlSqlQuery::data(int row, const QList<int> &roles) const
+{
+ Q_D(const QmlSqlQuery);
+ if (!d->query)
+ d->prepareQuery();
+ QHash<int, QVariant> result;
+
+ if (!d->isSel)
+ return result;
+
+ Q_ASSERT(row >= 0 && row <= d->count);
+
+ if (!d->requireCache)
+ d->query->seek(row);
+
+ for (int i = 0; i < roles.count(); ++i) {
+ int column = roles[i];
+ Q_ASSERT(column >= 0 && column < d->cache.size());
+ if (d->requireCache)
+ result.insert(column, d->cache[column].at(row));
+ else
+ result.insert(column, d->query->value(column));
+ }
+ return result;
+}
+
+/*!
+ Returns the number of rows in the query result set. Returns 0 if
+ the query is not a select statement.
+
+ \sa data(), roles(), toString()
+*/
+int QmlSqlQuery::count() const
+{
+ Q_D(const QmlSqlQuery);
+ if (!d->query)
+ d->prepareQuery();
+ return d->count;
+}
+
+/*!
+ Returns the list of role integer identifiers for the query result set.
+ Returns and empty list if the query is not a select statement.
+
+ \sa data(), count(), toString()
+*/
+QList<int> QmlSqlQuery::roles() const
+{
+ Q_D(const QmlSqlQuery);
+ if (!d->query)
+ d->prepareQuery();
+
+ if (!d->isSel)
+ return QList<int>();
+
+ if (d->roleNames.isEmpty() && !d->requireCache) {
+ d->query->seek(0);
+ d->grabRoles();
+ }
+
+ return d->roles;
+}
+
+/*!
+ Returns the corresponding role name for the given \a role identifier.
+
+ \sa data(), roles(), toString()
+*/
+QString QmlSqlQuery::toString(int role) const
+{
+ Q_D(const QmlSqlQuery);
+ if (!d->query)
+ d->prepareQuery();
+
+ if (d->roleNames.isEmpty() && !d->requireCache) {
+ d->query->seek(0);
+ d->grabRoles();
+ }
+
+ return d->roleNames[role];
+}
+
+/*!
+ Returns information about the last error that occurred on the query.
+*/
+QString QmlSqlQuery::lastError() const
+{
+ Q_D(const QmlSqlQuery);
+ if (d->query)
+ return d->query->lastError().text();
+ return QString();
+}
+
+/*!
+ \reimp
+*/
+void QmlSqlQuery::classComplete()
+{
+ Q_D(QmlSqlQuery);
+ if (!d->query)
+ d->prepareQuery();
+}
+
+/*!
+ \internal
+ Rebinds the query, and if needed, emits rows inserted or rows
+ added so any attached ListView elements will correctly.
+
+ This slot is called automatically when the SqlBind elements in
+ the bindings property of the query change.
+*/
+void QmlSqlQuery::resetBinds()
+{
+ Q_D(QmlSqlQuery);
+ if (!d->query)
+ return;
+ int oldcount = d->count;
+ d->cache.resize(0);
+ d->roles.clear();
+ d->roleNames.clear();
+ d->bindQuery();
+ if (d->isSel) {
+ if (!d->query->isActive()) {
+ if (!d->query->exec())
+ qWarning() << "failed to execute query" << d->query->lastQuery() << d->query->boundValues() << d->query->lastError().text();
+ }
+ d->cacheQuery(); // may finish query
+ emitChanges(oldcount);
+ }
+}
+
+/*!
+ Executes the query. For SELECT statements this is normally only required
+ if the database changes outside of the SQL query element. Statements that
+ modify the database, such as UPDATE and INSERT, will not be applied until
+ this function is called.
+*/
+void QmlSqlQuery::exec()
+{
+ Q_D(QmlSqlQuery);
+ if (!d->query)
+ d->prepareQuery();
+ Q_ASSERT(d->query);
+
+ if (d->isSel) {
+ int oldcount = d->count;
+ d->cache.resize(0);
+ d->roles.clear();
+ d->roleNames.clear();
+ if (!d->query->exec())
+ qWarning() << "failed to execute query" << d->query->lastQuery() << d->query->boundValues() << d->query->lastError().text();
+ d->cacheQuery(); // may finish query
+ emitChanges(oldcount);
+ } else {
+ if (!d->query->exec())
+ qWarning() << "failed to execute query" << d->query->lastQuery() << d->query->boundValues() << d->query->lastError().text();
+ d->query->finish();
+ }
+}
+
+/*!
+ \internal
+
+ Resets the query and query cache.
+*/
+void QmlSqlQuery::resetQuery()
+{
+ Q_D(QmlSqlQuery);
+ Q_ASSERT(d->query != 0);
+ delete d->query;
+ d->query = 0;
+ d->cache.resize(0);
+ d->roles.clear();
+ d->roleNames.clear();
+ int oldcount = d->count;
+ d->prepareQuery();
+ emitChanges(oldcount);
+}
+
+/*!
+ \internal
+
+ emits row number changes based of differences between the given
+ \a oldcount and the current count of the query result set.
+*/
+void QmlSqlQuery::emitChanges(int oldcount)
+{
+ Q_D(QmlSqlQuery);
+ if (d->count > oldcount)
+ emit itemsInserted(oldcount, d->count-oldcount);
+ else if (d->count < oldcount)
+ emit itemsRemoved(d->count, oldcount-d->count);
+ if (d->count > 0 && oldcount > 0)
+ emit itemsChanged(0, qMin(d->count, oldcount), roles());
+}
+
+/*
+ Prepares the query. If the query starts with SELECT it is assumed to
+ be a SELECT statement and the query is also executed.
+*/
+void QmlSqlQueryPrivate::prepareQuery() const
+{
+ QObject *object = qvariant_cast<QObject*>(connectionVariant);
+ QmlSqlConnection *connection = qobject_cast<QmlSqlConnection *>(object);
+ QString connectionString = qvariant_cast<QString>(connectionVariant);
+
+ Q_ASSERT(query == 0);
+ QSqlDatabase db = connection ? connection->database()
+ : QSqlDatabase::database(connectionString.isEmpty()
+ ? QLatin1String(QSqlDatabase::defaultConnection)
+ : connectionString, false);
+
+ if (!db.isOpen()) {
+ count = 0;
+ return;
+ }
+
+ query = new QSqlQuery(db);
+
+ requireCache =
+ query->driver()->hasFeature(QSqlDriver::SimpleLocking)
+ || !query->driver()->hasFeature(QSqlDriver::QuerySize);
+
+ if (requireCache)
+ query->setForwardOnly(true);
+ if (!query->prepare(queryText))
+ qWarning() << "failed to prepare query" << query->lastQuery() << query->lastError().text();
+ bindQuery();
+ if (isSel) {
+ if (!query->exec())
+ qWarning() << "failed to execute query" << query->lastQuery() << query->boundValues() << query->lastError().text();
+ cacheQuery();
+ }
+}
+
+/*
+ Binds values into the prepared query using the bindings property of the SqlQuery element.
+*/
+void QmlSqlQueryPrivate::bindQuery() const
+{
+ for (int i = 0; i < binds.count(); ++i) {
+ QmlSqlBind *bind = binds.at(i);
+ if (bind->name().isEmpty()) {
+ query->bindValue(i, bind->value());
+ } else {
+ query->bindValue(bind->name(), bind->value());
+ }
+ }
+}
+
+/*
+ If the query is connected to a database with simple locking or
+ that cannot ask for the count of a result set, caches the required
+ data of the query and finishes the query to release locks.
+
+ Otherwise just caches the count of the query.
+*/
+void QmlSqlQueryPrivate::cacheQuery() const
+{
+ if (requireCache) {
+ int row = 0;
+ while (query->next()) {
+ if (roleNames.isEmpty()) {
+ grabRoles();
+ cache.resize(roleNames.count());
+ }
+ Q_ASSERT(cache.size() > 0);
+ for (int i = 0; i < cache.size(); ++i) {
+ cache[i].append(query->value(i));
+ }
+ row++;
+ }
+ count = row;
+ query->finish();
+ } else {
+ count = query->size();
+ }
+}
+
+/*
+ Gets the column names for the roles of the SqlQuery element.
+
+ The query must be active and on a valid row.
+*/
+void QmlSqlQueryPrivate::grabRoles() const
+{
+ Q_ASSERT(query);
+ Q_ASSERT(query->isValid());
+ Q_ASSERT(roleNames.isEmpty());
+ Q_ASSERT(roles.isEmpty());
+
+ QSqlRecord record = query->record();
+ for (int i = 0; i < record.count(); ++i) {
+ roleNames.append(record.fieldName(i));
+ roles.append(i);
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/extra/qmlsqlquery.h b/src/declarative/extra/qmlsqlquery.h
new file mode 100644
index 0000000..984483c
--- /dev/null
+++ b/src/declarative/extra/qmlsqlquery.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSQLQUERYMODEL_H
+#define QMLSQLQUERYMODEL_H
+
+#include <qml.h>
+#include <QListModelInterface>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlSqlBindPrivate;
+class Q_DECLARATIVE_EXPORT QmlSqlBind : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QVariant value READ value WRITE setValue)
+
+ Q_CLASSINFO("DefaultValue", "value");
+
+public:
+ QmlSqlBind(QObject *parent = 0);
+ ~QmlSqlBind();
+
+ QString name() const;
+ QVariant value() const;
+
+ void setName(const QString &name);
+ void setValue(const QVariant &);
+
+ virtual void classComplete();
+
+Q_SIGNALS:
+ void valueChanged();
+
+private:
+ Q_DISABLE_COPY(QmlSqlBind)
+ Q_DECLARE_PRIVATE(QmlSqlBind)
+};
+
+QML_DECLARE_TYPE(QmlSqlBind);
+
+class QSqlQuery;
+class QmlSqlQueryPrivate;
+class Q_DECLARATIVE_EXPORT QmlSqlQuery : public QListModelInterface, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString query READ query WRITE setQuery)
+ Q_PROPERTY(QVariant connection READ connection WRITE setConnection)
+ Q_PROPERTY(QString lastError READ lastError)
+
+ Q_PROPERTY(QmlList<QmlSqlBind *> *bindings READ bindings)
+
+ Q_CLASSINFO("DefaultProperty", "query")
+public:
+ QmlSqlQuery(QObject *parent = 0);
+ ~QmlSqlQuery();
+
+ QString query() const;
+ void setQuery(const QString &);
+
+ QVariant connection() const;
+ void setConnection(const QVariant &);
+
+ virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+ virtual int count() const;
+ virtual QList<int> roles() const;
+ virtual QString toString(int role) const;
+
+ QString lastError() const;
+
+ virtual void classComplete();
+
+ QmlList<QmlSqlBind *> *bindings();
+ const QmlList<QmlSqlBind *> *bindings() const;
+
+public slots:
+ void exec();
+
+private slots:
+ void resetBinds();
+ void resetQuery();
+
+private:
+ void emitChanges(int oldcount);
+
+ Q_DISABLE_COPY(QmlSqlQuery)
+ Q_DECLARE_PRIVATE(QmlSqlQuery)
+};
+
+QML_DECLARE_TYPE(QmlSqlQuery);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
+
diff --git a/src/declarative/extra/qmlxmllistmodel.cpp b/src/declarative/extra/qmlxmllistmodel.cpp
new file mode 100644
index 0000000..bba817d
--- /dev/null
+++ b/src/declarative/extra/qmlxmllistmodel.cpp
@@ -0,0 +1,385 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlxmllistmodel.h"
+#include "private/qobject_p.h"
+
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QDebug>
+#include <QXmlQuery>
+#include <QXmlResultItems>
+#include <QXmlNodeModelIndex>
+#include <QBuffer>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(XmlListModelRole, Role);
+QML_DEFINE_TYPE(QmlXmlListModel, XmlListModel);
+
+//TODO: do something smart while waiting for data to load
+// error handling (currently quite fragile)
+// profile doQuery and doSubquery
+// some sort of loading indication while we wait for initial data load (status property similar to QWebImage?)
+// support complex/nested objects?
+// how do we handle data updates (like rss feed -- usually items inserted at beginning)
+
+/*!
+ \qmlclass XmlListModel
+ \brief The XmlListModel class allows you to specify a model using XQuery.
+
+ XmlListModel allows you to construct a model from XML data that can then be used as a data source
+ for the view classes (ListView, PathView, GridView) and any other classes that interact with model
+ data (like Repeater).
+
+ The following is an example of a model containing news from a Yahoo RSS feed:
+ \qml
+ XmlListModel {
+ id: FeedModel
+ source: "http://rss.news.yahoo.com/rss/oceania"
+ query: "doc($src)/rss/channel/item"
+ Role { name: "title"; query: "title/string()" }
+ Role { name: "link"; query: "link/string()" }
+ Role { name: "description"; query: "description/string()"; isCData: true }
+ }
+ \endqml
+ \note The model is currently static, so the above is really just a snapshot of an RSS feed.
+*/
+
+class QmlXmlListModelPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlXmlListModel)
+public:
+ QmlXmlListModelPrivate() : isClassComplete(false), size(-1), highestRole(Qt::UserRole), reply(0), roleObjects(this) {}
+
+ bool isClassComplete;
+ QString src;
+ QString query;
+ QString namespaces;
+ QList<int> roles;
+ QStringList roleNames;
+ mutable QList<QList<QVariant> > data;
+ int size;
+ int highestRole;
+ QNetworkReply *reply;
+ mutable QByteArray xml;
+ QString prefix;
+
+ struct RoleList : public QmlConcreteList<XmlListModelRole *>
+ {
+ RoleList(QmlXmlListModelPrivate *p)
+ : model(p) {}
+ virtual void append(XmlListModelRole *role) {
+ QmlConcreteList<XmlListModelRole *>::append(role);
+ model->roles << model->highestRole;
+ model->roleNames << role->name();
+ ++model->highestRole;
+ }
+ //XXX clear, removeAt, and insert need to invalidate any cached data (in data table) as well
+ // (and the model should emit the appropriate signals)
+ virtual void clear()
+ {
+ model->roles.clear();
+ model->roleNames.clear();
+ QmlConcreteList<XmlListModelRole *>::clear();
+ }
+ virtual void removeAt(int i)
+ {
+ model->roles.removeAt(i);
+ model->roleNames.removeAt(i);
+ QmlConcreteList<XmlListModelRole *>::removeAt(i);
+ }
+ virtual void insert(int i, XmlListModelRole *role)
+ {
+ QmlConcreteList<XmlListModelRole *>::insert(i, role);
+ model->roles.insert(i, model->highestRole);
+ model->roleNames.insert(i, role->name());
+ ++model->highestRole;
+ }
+
+ QmlXmlListModelPrivate *model;
+ };
+
+ RoleList roleObjects;
+};
+
+QmlXmlListModel::QmlXmlListModel(QObject *parent)
+ : QListModelInterface(*(new QmlXmlListModelPrivate), parent)
+{
+ Q_D(QmlXmlListModel);
+}
+
+QmlXmlListModel::~QmlXmlListModel()
+{
+}
+
+QmlList<XmlListModelRole *> *QmlXmlListModel::roleObjects()
+{
+ Q_D(QmlXmlListModel);
+ return &d->roleObjects;
+}
+
+QHash<int,QVariant> QmlXmlListModel::data(int index, const QList<int> &roles) const
+{
+ Q_D(const QmlXmlListModel);
+ QHash<int, QVariant> rv;
+
+ if (index > d->data.count() - 1)
+ doSubquery(index);
+
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ int roleIndex = d->roles.indexOf(role);
+ rv.insert(role, d->data.at(index).at(roleIndex));
+ }
+ return rv;
+}
+
+int QmlXmlListModel::count() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->size;
+}
+
+QList<int> QmlXmlListModel::roles() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->roles;
+}
+
+QString QmlXmlListModel::toString(int role) const
+{
+ Q_D(const QmlXmlListModel);
+ int index = d->roles.indexOf(role);
+ if (index == -1)
+ return QString();
+ return d->roleNames.at(index);
+}
+
+QString QmlXmlListModel::source() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->src;
+}
+
+void QmlXmlListModel::setSource(const QString &src)
+{
+ Q_D(QmlXmlListModel);
+ if (d->src != src) {
+ d->src = src;
+ reload();
+ }
+}
+
+QString QmlXmlListModel::query() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->query;
+}
+
+void QmlXmlListModel::setQuery(const QString &query)
+{
+ Q_D(QmlXmlListModel);
+ if (d->query != query) {
+ d->query = query;
+ reload();
+ }
+}
+
+QString QmlXmlListModel::namespaceDeclarations() const
+{
+ Q_D(const QmlXmlListModel);
+ return d->namespaces;
+}
+
+void QmlXmlListModel::setNamespaceDeclarations(const QString &declarations)
+{
+ Q_D(QmlXmlListModel);
+ if (d->namespaces != declarations) {
+ d->namespaces = declarations;
+ reload();
+ }
+}
+
+void QmlXmlListModel::classComplete()
+{
+ Q_D(QmlXmlListModel);
+ d->isClassComplete = true;
+ reload();
+}
+
+void QmlXmlListModel::reload()
+{
+ Q_D(QmlXmlListModel);
+
+ if (!d->isClassComplete)
+ return;
+
+ //clear existing data
+ d->size = 0;
+ int count = d->data.count();
+ d->data.clear();
+ if (count > 0)
+ emit itemsRemoved(0, count);
+
+ if (d->src.isEmpty()) {
+ qWarning() << "Can't load empty src string";
+ return;
+ }
+
+ if (d->reply) {
+ d->reply->abort();
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+
+ QNetworkRequest req((QUrl(d->src)));
+ req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+ d->reply = qmlContext(this)->engine()->networkAccessManager()->get(req);
+ QObject::connect(d->reply, SIGNAL(finished()),
+ this, SLOT(requestFinished()));
+}
+
+void QmlXmlListModel::requestFinished()
+{
+ Q_D(QmlXmlListModel);
+ if (d->reply->error() != QNetworkReply::NoError) {
+ d->reply->deleteLater();
+ d->reply = 0;
+ } else {
+ QByteArray data = d->reply->readAll();
+ doQuery(data);
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+}
+
+void QmlXmlListModel::doQuery(QByteArray &rawData)
+{
+ Q_D(QmlXmlListModel);
+ QString r;
+ QXmlQuery query;
+ QBuffer rawBuffer(&rawData);
+ rawBuffer.open(QIODevice::ReadOnly);
+ query.bindVariable(QLatin1String("src"), &rawBuffer);
+ query.setQuery(d->namespaces + d->query);
+ query.evaluateTo(&r);
+ //qDebug() << r;
+
+ //always need a single root element
+ QByteArray xml = "<dummy:items xmlns:dummy=\"http://qtsotware.com/dummy\">\n" + r.toUtf8() + "</dummy:items>";
+ QBuffer b(&xml);
+ b.open(QIODevice::ReadOnly);
+ //qDebug() << xml;
+
+ QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + d->namespaces;
+ QString prefix = QLatin1String("doc($inputDocument)/dummy:items") +
+ d->query.mid(d->query.lastIndexOf(QLatin1Char('/')));
+
+ //figure out how many items we are dealing with
+ int count = -1;
+ {
+ QXmlResultItems result;
+ QXmlQuery countquery;
+ countquery.bindVariable(QLatin1String("inputDocument"), &b);
+ countquery.setQuery(namespaces + QLatin1String("count(") + prefix + QLatin1String(")"));
+ countquery.evaluateTo(&result);
+ QXmlItem item(result.next());
+ if (item.isAtomicValue())
+ count = item.toAtomicValue().toInt();
+ b.seek(0);
+ prefix += QLatin1String("[%1]/");
+ }
+ //qDebug() << count;
+
+ QXmlQuery subquery;
+ subquery.bindVariable(QLatin1String("inputDocument"), &b);
+ d->prefix = namespaces + prefix;
+ d->xml = xml;
+
+ d->size = count;
+
+ if (count > 0)
+ emit itemsInserted(0, count);
+}
+
+void QmlXmlListModel::doSubquery(int index) const
+{
+ Q_D(const QmlXmlListModel);
+ //qDebug() << "doSubQuery" << index;
+ QBuffer b(&d->xml);
+ b.open(QIODevice::ReadOnly);
+
+ QXmlQuery subquery;
+ subquery.bindVariable(QLatin1String("inputDocument"), &b);
+
+ //XXX should we use an array of objects or something else rather than a table?
+ for (int j = d->data.count(); j <= index; ++j) {
+ QList<QVariant> resultList;
+ for (int i = 0; i < d->roleObjects.size(); ++i) {
+ XmlListModelRole *role = d->roleObjects.at(i);
+ subquery.setQuery(d->prefix.arg(j+1) + role->query());
+ if (role->isStringList()) {
+ QStringList data;
+ subquery.evaluateTo(&data);
+ resultList << QVariant(data);
+ //qDebug() << data;
+ } else {
+ QString s;
+ subquery.evaluateTo(&s);
+ if (role->isCData()) {
+ //un-escape
+ s.replace(QLatin1String("&lt;"), QLatin1String("<"));
+ s.replace(QLatin1String("&gt;"), QLatin1String(">"));
+ s.replace(QLatin1String("&amp;"), QLatin1String("&"));
+ }
+ resultList << s.trimmed();
+ //qDebug() << s;
+ }
+ b.seek(0);
+ }
+ d->data << resultList;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/extra/qmlxmllistmodel.h b/src/declarative/extra/qmlxmllistmodel.h
new file mode 100644
index 0000000..2e932cb
--- /dev/null
+++ b/src/declarative/extra/qmlxmllistmodel.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLXMLLISTMODEL_H
+#define QMLXMLLISTMODEL_H
+
+#include <qml.h>
+#include <QListModelInterface>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlContext;
+class Q_DECLARATIVE_EXPORT XmlListModelRole : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QString query READ query WRITE setQuery)
+ Q_PROPERTY(bool isCData READ isCData WRITE setIsCData)
+ Q_PROPERTY(bool isStringList READ isStringList WRITE setIsStringList)
+
+public:
+ XmlListModelRole() : m_isList(false), m_isCData(false) {}
+ ~XmlListModelRole() {}
+
+ QString name() const { return m_name; }
+ void setName(const QString &name) { m_name = name; }
+
+ QString query() const { return m_query; }
+ void setQuery(const QString &query) { m_query = query; }
+
+ bool isStringList() const { return m_isList; }
+ void setIsStringList(bool b) { m_isList = b; }
+
+ bool isCData() const { return m_isCData; }
+ void setIsCData(bool b) { m_isCData = b; }
+
+private:
+ QString m_name;
+ QString m_query;
+ bool m_isList;
+ bool m_isCData;
+};
+QML_DECLARE_TYPE(XmlListModelRole);
+
+class QmlXmlListModelPrivate;
+class Q_DECLARATIVE_EXPORT QmlXmlListModel : public QListModelInterface, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString source READ source WRITE setSource)
+ Q_PROPERTY(QString query READ query WRITE setQuery)
+ Q_PROPERTY(QString namespaceDeclarations READ namespaceDeclarations WRITE setNamespaceDeclarations)
+ Q_PROPERTY(QmlList<XmlListModelRole *> *roles READ roleObjects)
+ Q_CLASSINFO("DefaultProperty", "roles")
+public:
+ QmlXmlListModel(QObject *parent = 0);
+ ~QmlXmlListModel();
+
+ virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+ virtual int count() const;
+ virtual QList<int> roles() const;
+ virtual QString toString(int role) const;
+
+ QmlList<XmlListModelRole *> *roleObjects();
+
+ QString source() const;
+ void setSource(const QString&);
+
+ QString query() const;
+ void setQuery(const QString&);
+
+ QString namespaceDeclarations() const;
+ void setNamespaceDeclarations(const QString&);
+
+ virtual void classComplete();
+
+public Q_SLOTS:
+ void reload();
+
+protected:
+ void doQuery(QByteArray &rawData);
+ void doSubquery(int index) const;
+
+private Q_SLOTS:
+ void requestFinished();
+
+private:
+ Q_DECLARE_PRIVATE(QmlXmlListModel)
+ Q_DISABLE_COPY(QmlXmlListModel)
+};
+
+QML_DECLARE_TYPE(QmlXmlListModel);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLXMLLISTMODEL_H
diff --git a/src/declarative/extra/qnumberformat.cpp b/src/declarative/extra/qnumberformat.cpp
new file mode 100644
index 0000000..79e328a
--- /dev/null
+++ b/src/declarative/extra/qnumberformat.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnumberformat.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QNumberFormat,NumberFormat);
+
+QNumberFormat::QNumberFormat(QObject *parent) : QObject(parent), _number(0), _type(Decimal),
+ _groupingSize(0)
+{
+ _locale = QLocale::system();
+ _groupingSeparator = _locale.groupSeparator();
+ _decimalSeparator = _locale.decimalPoint();
+ _currencySymbol = QLatin1Char('$');
+}
+
+QNumberFormat::~QNumberFormat()
+{
+
+}
+
+void QNumberFormat::updateText()
+{
+ QTime t;
+ t.start();
+ static int totalTime;
+
+ handleFormat();
+
+ totalTime += t.elapsed();
+ emit textChanged();
+}
+
+void QNumberFormat::handleFormat()
+{
+ // ### is extremely messy
+ if (_format.isEmpty()) {
+ _text = QString(QLatin1String("%1")).arg(_number, -1, 'f', -1);
+ return;
+ }
+
+ QString inputString;
+
+ // ### possible to use the following parsed data in the future
+
+ int remainingLength = _format.size();
+ int currentIndex = _format.size()-1;
+
+ int maxDigits = 0;
+ int minDigits = 0;
+ int decimalLength = 0;
+
+ while (remainingLength > 0) {
+ switch(_format.at(currentIndex).unicode()) {
+ case ',':
+ if (decimalLength && !_groupingSize)
+ setGroupingSize(maxDigits - decimalLength);
+ else if (!_groupingSize)
+ setGroupingSize(maxDigits);
+ break;
+ case '.':
+ if (!decimalLength)
+ decimalLength = maxDigits;
+ break;
+ case '0':
+ minDigits++;
+ case '#':
+ maxDigits++;
+ break;
+ default:
+ break;
+ }
+ currentIndex--;
+ remainingLength--;
+ }
+
+ // round given the decimal length/precision
+ inputString = QString(QLatin1String("%1")).arg(_number, -1, 'f', decimalLength);
+
+ QStringList parts = inputString.split(QLatin1Char('.'));
+ QStringList formatParts = _format.split(QLatin1Char('.'));
+
+ if (formatParts.size() > 2 || parts.size() > 2 )
+ return;
+
+ QString formatInt = formatParts.at(0);
+
+ QString formatDec;
+ if (formatParts.size() == 2)
+ formatDec = formatParts.at(1);
+
+ QString integer = parts.at(0);
+
+ QString decimal;
+ if (parts.size() == 2)
+ decimal = parts.at(1);
+
+ QString outputDecimal = formatDecimal(formatDec, decimal);
+ QString outputInteger = formatInteger(formatInt, integer);
+
+ // insert separators
+ if (_groupingSize) {
+ unsigned int count = 0;
+ for (int i = outputInteger.size()-1; i > 0; i--) {
+ if (outputInteger.at(i).digitValue() >= 0) {
+ if (count == _groupingSize - 1) {
+ count = 0;
+ outputInteger.insert(i, _groupingSeparator);
+ }
+ else
+ count++;
+ }
+ }
+ }
+ if (!outputDecimal.isEmpty())
+ _text = outputInteger + _decimalSeparator + outputDecimal;
+ else
+ _text = outputInteger;
+}
+
+QString QNumberFormat::formatInteger(const QString &formatInt, const QString &integer)
+{
+ if (formatInt.isEmpty() || integer.isEmpty())
+ return QString();
+
+ QString outputInteger;
+ int formatIndex = formatInt.size()-1;
+
+ //easier for carry?
+ for (int index= integer.size()-1; index >= 0; index--) {
+ if (formatIndex < 0) {
+ outputInteger.push_front(integer.at(index));
+ }
+ else {
+ switch(formatInt.at(formatIndex).unicode()) {
+ case '0':
+ if (index > integer.size()-1) {
+ outputInteger.push_front(QLatin1Char('0'));
+ break;
+ }
+ case '#':
+ outputInteger.push_front(integer.at(index));
+ break;
+ case ',':
+ index++;
+ break;
+ default:
+ outputInteger.push_front(formatInt.at(formatIndex));
+ index++;
+ break;
+ }
+ formatIndex--;
+ }
+ }
+ while (formatIndex >= 0) {
+ if (formatInt.at(formatIndex).unicode() != '#' && formatInt.at(formatIndex).unicode() != ',')
+ outputInteger.push_front(formatInt.at(formatIndex));
+ formatIndex--;
+ }
+ return outputInteger;
+}
+
+QString QNumberFormat::formatDecimal(const QString &formatDec, const QString &decimal)
+{
+ QString outputDecimal;
+
+ // up to max 6 decimal places
+ for (int index=formatDec.size()-1; index >= 0; index--) {
+ switch(formatDec.at(index).unicode()) {
+ case '0':
+ outputDecimal.push_front(decimal.at(index));
+ break;
+ case '#':
+ if (decimal.at(index) != QLatin1Char('0') || outputDecimal.size() > 0)
+ outputDecimal.push_front(decimal.at(index));
+ break;
+ default:
+ outputDecimal.push_front(formatDec.at(index));
+ break;
+ }
+ }
+ return outputDecimal;
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/extra/qnumberformat.h b/src/declarative/extra/qnumberformat.h
new file mode 100644
index 0000000..6ee333c
--- /dev/null
+++ b/src/declarative/extra/qnumberformat.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NUMBERFORMAT_H
+#define NUMBERFORMAT_H
+
+#include "qml.h"
+#include <QtGui>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+// TODO
+// be able to set Locale, instead of default system for dynamic formatting
+// add currency support
+// add additional syntax, extend to format scientific, percentiles, significant digits etc
+
+
+class QNumberFormat : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(NumberType)
+public:
+ QNumberFormat(QObject *parent=0);
+ ~QNumberFormat();
+
+ enum NumberType {
+ Percent,
+ Scientific,
+ Currency,
+ Decimal
+ };
+
+ //external property, only visible
+ Q_PROPERTY(QString text READ text NOTIFY textChanged);
+
+ //mutatable properties to modify the output (text)
+ Q_PROPERTY(qreal number READ number WRITE setNumber);
+ Q_PROPERTY(QString format READ format WRITE setFormat);
+ Q_PROPERTY(QLocale locale READ locale WRITE setLocale);
+
+ //Format specific settings
+ Q_PROPERTY(unsigned short groupingSeparator READ groupingSeparator WRITE setGroupingSeparator);
+ Q_PROPERTY(unsigned short decimalSeperator READ decimalSeparator WRITE setDecimalSeparator);
+ Q_PROPERTY(unsigned int groupingSize READ groupingSize WRITE setGroupingSize);
+ Q_PROPERTY(unsigned short currencySymbol READ currencySymbol WRITE setCurrencySymbol);
+
+
+ QString text() const { return _text; }
+
+ qreal number() const { return _number; }
+ void setNumber(qreal n) {
+ if (_number == n)
+ return;
+ _number = n;
+ updateText();
+ }
+
+ QString format() const { return _format; }
+ void setFormat(const QString &format) {
+ if (format.isEmpty())
+ _format = QString::null;
+ else if (_format == format)
+ return;
+
+ _format = format;
+ updateText();
+ }
+
+ QLocale locale() const { return _locale; }
+ void setLocale(const QLocale &locale) { _locale = locale; updateText(); }
+
+ //Do we deal with unicode standard? or create our own
+ // ### since this is the backend for the number conversions, we will use the unicode
+ // the front-end will handle the QChar/QString -> short int
+
+ unsigned short groupingSeparator() { return _groupingSeparator.unicode(); }
+ void setGroupingSeparator(unsigned short unicodeSymbol)
+ {
+ _groupingSeparator = QChar(unicodeSymbol);
+ }
+
+ unsigned short decimalSeparator() { return _decimalSeparator.unicode(); }
+ void setDecimalSeparator(unsigned short unicodeSymbol)
+ {
+ _decimalSeparator = QChar(unicodeSymbol);
+ }
+
+ unsigned short currencySymbol() { return _currencySymbol.unicode(); }
+ void setCurrencySymbol(unsigned short unicodeSymbol)
+ {
+ _currencySymbol = QChar(unicodeSymbol);
+ }
+
+ unsigned int groupingSize() { return _groupingSize; }
+ void setGroupingSize(unsigned int size)
+ {
+ _groupingSize = size;
+ }
+
+Q_SIGNALS:
+ void textChanged();
+
+private:
+ void updateText();
+ void handleFormat();
+ QString formatInteger(const QString &formatInt, const QString &integer);
+ QString formatDecimal(const QString &formatDec, const QString &decimal);
+
+ qreal _number;
+ NumberType _type;
+ QChar _groupingSeparator;
+ QChar _decimalSeparator;
+ QChar _currencySymbol;
+ unsigned int _groupingSize;
+
+ QLocale _locale;
+ QString _format;
+
+ // only hooked member at the moment
+ QString _text;
+
+};
+QML_DECLARE_TYPE(QNumberFormat);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/fx.pri b/src/declarative/fx/fx.pri
new file mode 100644
index 0000000..90820fa
--- /dev/null
+++ b/src/declarative/fx/fx.pri
@@ -0,0 +1,95 @@
+HEADERS += \
+ fx/qfxanchors.h \
+ fx/qfxanchors_p.h \
+ fx/qfxanimatedimageitem.h \
+ fx/qfxblendedimage.h \
+ fx/qfxblurfilter.h \
+ fx/qfxcomponentinstance.h \
+ fx/qfxcomponentinstance_p.h \
+ fx/qfxcontentwrapper.h \
+ fx/qfxcontentwrapper_p.h \
+ fx/qfxevents_p.h \
+ fx/qfxflickable.h \
+ fx/qfxflickable_p.h \
+ fx/qfxflipable.h \
+ fx/qfxfocuspanel.h \
+ fx/qfxfocusrealm.h \
+ fx/qfxgridview.h \
+ fx/qfxhighlightfilter.h \
+ fx/qfximage.h \
+ fx/qfxpainteditem.h \
+ fx/qfxpainteditem_p.h \
+ fx/qfximage_p.h \
+ fx/qfxitem.h \
+ fx/qfxitem_p.h \
+ fx/qfxkeyactions.h \
+ fx/qfxkeyproxy.h \
+ fx/qfxlayouts.h \
+ fx/qfxlayouts_p.h \
+ fx/qfxmouseregion.h \
+ fx/qfxmouseregion_p.h \
+ fx/qfxparticles.h \
+ fx/qfxpath.h \
+ fx/qfxpath_p.h \
+ fx/qfxpathview.h \
+ fx/qfxpathview_p.h \
+ fx/qfxrect.h \
+ fx/qfxrect_p.h \
+ fx/qfxreflectionfilter.h \
+ fx/qfxrepeater.h \
+ fx/qfxrepeater_p.h \
+ fx/qfxscalegrid.h \
+ fx/qfxshadowfilter.h \
+ fx/qfxtextedit.h \
+ fx/qfxtextedit_p.h \
+ fx/qfxtext.h \
+ fx/qfxtext_p.h \
+ fx/qfxtransform.h \
+ fx/qfxpixmap.cpp \
+ fx/qfxvisualitemmodel.h \
+ fx/qfxlistview.h \
+ fx/qfxwidgetcontainer.h \
+
+SOURCES += \
+ fx/qfxanchors.cpp \
+ fx/qfxanimatedimageitem.cpp \
+ fx/qfxblendedimage.cpp \
+ fx/qfxblurfilter.cpp \
+ fx/qfxcomponentinstance.cpp \
+ fx/qfxcontentwrapper.cpp \
+ fx/qfxevents.cpp \
+ fx/qfxflickable.cpp \
+ fx/qfxflipable.cpp \
+ fx/qfxfocuspanel.cpp \
+ fx/qfxfocusrealm.cpp \
+ fx/qfxgridview.cpp \
+ fx/qfxhighlightfilter.cpp \
+ fx/qfximage.cpp \
+ fx/qfxpainteditem.cpp \
+ fx/qfxitem.cpp \
+ fx/qfxkeyactions.cpp \
+ fx/qfxkeyproxy.cpp \
+ fx/qfxlayouts.cpp \
+ fx/qfxmouseregion.cpp \
+ fx/qfxparticles.cpp \
+ fx/qfxpath.cpp \
+ fx/qfxpathview.cpp \
+ fx/qfxrect.cpp \
+ fx/qfxreflectionfilter.cpp \
+ fx/qfxrepeater.cpp \
+ fx/qfxscalegrid.cpp \
+ fx/qfxshadowfilter.cpp \
+ fx/qfxtext.cpp \
+ fx/qfxtextedit.cpp \
+ fx/qfxtransform.cpp \
+ fx/qfxpixmap.cpp \
+ fx/qfxvisualitemmodel.cpp \
+ fx/qfxlistview.cpp \
+ fx/qfxwidgetcontainer.cpp \
+
+contains(QT_CONFIG, webkit) {
+ QT+=webkit
+ SOURCES += fx/qfxwebview.cpp
+ HEADERS += fx/qfxwebview.h
+}
+
diff --git a/src/declarative/fx/qfxanchors.cpp b/src/declarative/fx/qfxanchors.cpp
new file mode 100644
index 0000000..53d0187
--- /dev/null
+++ b/src/declarative/fx/qfxanchors.cpp
@@ -0,0 +1,997 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxanchors_p.h"
+#include "qfxitem.h"
+#include <QDebug>
+#include <QtDeclarative/qmlinfo.h>
+#include <QtDeclarative/qmlbindablevalue.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(QFxAnchors,Anchors);
+
+//TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
+//TODO: baseline support
+//TODO: support non-parent, non-sibling (need to find lowest common ancestor)
+
+//### const item?
+//local position
+static qreal position(QFxItem *item, QFxAnchorLine::AnchorLine anchorLine)
+{
+ qreal ret = 0.0;
+ switch(anchorLine) {
+ case QFxAnchorLine::Left:
+ ret = item->x();
+ break;
+ case QFxAnchorLine::Right:
+ ret = item->x() + item->width();
+ break;
+ case QFxAnchorLine::Top:
+ ret = item->y();
+ break;
+ case QFxAnchorLine::Bottom:
+ ret = item->y() + item->height();
+ break;
+ case QFxAnchorLine::HCenter:
+ ret = item->x() + item->width()/2;
+ break;
+ case QFxAnchorLine::VCenter:
+ ret = item->y() + item->height()/2;
+ break;
+ case QFxAnchorLine::Baseline:
+ ret = item->y() + item->baselineOffset();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+//position when origin is 0,0
+static qreal adjustedPosition(QFxItem *item, QFxAnchorLine::AnchorLine anchorLine)
+{
+ int ret = 0;
+ switch(anchorLine) {
+ case QFxAnchorLine::Left:
+ ret = 0;
+ break;
+ case QFxAnchorLine::Right:
+ ret = item->width();
+ break;
+ case QFxAnchorLine::Top:
+ ret = 0;
+ break;
+ case QFxAnchorLine::Bottom:
+ ret = item->height();
+ break;
+ case QFxAnchorLine::HCenter:
+ ret = item->width()/2;
+ break;
+ case QFxAnchorLine::VCenter:
+ ret = item->height()/2;
+ break;
+ case QFxAnchorLine::Baseline:
+ ret = item->baselineOffset();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/*!
+ \internal
+ \class QFxAnchors
+ \ingroup group_layouts
+ \brief The QFxAnchors class provides a way to lay out items relative to other items.
+
+ \warning Currently, only anchoring to siblings or parent is supported.
+*/
+
+QFxAnchors::QFxAnchors(QObject *parent)
+ : QObject(*new QFxAnchorsPrivate(), parent)
+{
+
+}
+
+void QFxAnchors::fillChanged()
+{
+ Q_D(QFxAnchors);
+ if (!d->fill)
+ return;
+
+ if (d->fill == d->item->itemParent()) { //child-parent
+ d->item->setPos(QPointF(leftMargin(), topMargin()));
+ } else if (d->fill->itemParent() == d->item->itemParent()) { //siblings
+ d->item->setPos(QPointF(d->fill->x()+leftMargin(), d->fill->y()+topMargin()));
+ }
+ d->item->setWidth(d->fill->width()-leftMargin()-rightMargin());
+ d->item->setHeight(d->fill->height()-topMargin()-bottomMargin());
+}
+
+/*!
+ \property QFxAnchors::fill
+ \brief which item the item should fill.
+
+ This is a convenience property. It is the same as anchoring the left, right, top, and bottom
+ to another item's left, right, top, and bottom.
+*/
+QFxItem *QFxAnchors::fill() const
+{
+ Q_D(const QFxAnchors);
+ return d->fill;
+}
+
+void QFxAnchors::setFill(QFxItem *f)
+{
+ Q_D(QFxAnchors);
+ if (d->fill) {
+ QObject::disconnect(d->fill, SIGNAL(leftChanged()), this, SLOT(fillChanged()));
+ QObject::disconnect(d->fill, SIGNAL(topChanged()), this, SLOT(fillChanged()));
+ QObject::disconnect(d->fill, SIGNAL(widthChanged()), this, SLOT(fillChanged()));
+ QObject::disconnect(d->fill, SIGNAL(heightChanged()), this, SLOT(fillChanged()));
+ QObject::disconnect(this, SIGNAL(leftMarginChanged()), this, SLOT(fillChanged()));
+ QObject::disconnect(this, SIGNAL(topMarginChanged()), this, SLOT(fillChanged()));
+ QObject::disconnect(this, SIGNAL(rightMarginChanged()), this, SLOT(fillChanged()));
+ QObject::disconnect(this, SIGNAL(bottomMarginChanged()), this, SLOT(fillChanged()));
+ }
+
+ d->fill = f;
+
+ if (d->fill) {
+ if (d->fill == d->item->itemParent()) { //child-parent
+ QObject::connect(d->fill, SIGNAL(widthChanged()), this, SLOT(fillChanged()));
+ QObject::connect(d->fill, SIGNAL(heightChanged()), this, SLOT(fillChanged()));
+ } else if (f->itemParent() == d->item->itemParent()) { //siblings
+ QObject::connect(d->fill, SIGNAL(leftChanged()), this, SLOT(fillChanged()));
+ QObject::connect(d->fill, SIGNAL(topChanged()), this, SLOT(fillChanged()));
+ QObject::connect(d->fill, SIGNAL(widthChanged()), this, SLOT(fillChanged()));
+ QObject::connect(d->fill, SIGNAL(heightChanged()), this, SLOT(fillChanged()));
+ } else {
+ qmlInfo(d->item) << "Can't anchor to an item that isn't a parent or sibling.";
+ }
+ }
+ QObject::connect(this, SIGNAL(leftMarginChanged()), this, SLOT(fillChanged()));
+ QObject::connect(this, SIGNAL(topMarginChanged()), this, SLOT(fillChanged()));
+ QObject::connect(this, SIGNAL(rightMarginChanged()), this, SLOT(fillChanged()));
+ QObject::connect(this, SIGNAL(bottomMarginChanged()), this, SLOT(fillChanged()));
+ fillChanged(); //### can/should we defer until component completion?
+}
+
+/*!
+ \property QFxAnchors::centeredIn
+ \brief which item the item should stay centered in.
+
+ This is a convenience property. It is the same as anchoring the horizontalCenter
+ and verticalCenter to another item's horizontalCenter and verticalCenter.
+*/
+QFxItem *QFxAnchors::centeredIn() const
+{
+ Q_D(const QFxAnchors);
+ return d->centeredIn;
+}
+
+void QFxAnchors::setCenteredIn(QFxItem* c)
+{
+ Q_D(QFxAnchors);
+ if (!c){
+ qmlInfo(d->item) << "Cannot center in null item.";
+ return;
+ }
+ if (c != d->item->itemParent() && c->itemParent() != d->item->itemParent()){
+ qmlInfo(d->item) << "Can't anchor to an item that isn't a parent or sibling.";
+ return;
+ }
+ d->centeredIn = c;
+ setHorizontalCenter(c->horizontalCenter());
+ setVerticalCenter(c->verticalCenter());
+}
+
+void QFxAnchorsPrivate::connectVHelper(const QFxAnchorLine &edge)
+{
+ //### should we do disconnects first? (will it be called more than once?)
+ Q_Q(QFxAnchors);
+ if (edge.item == item->itemParent()) { //child-parent
+ switch(edge.anchorLine) {
+ case QFxAnchorLine::Bottom:
+ case QFxAnchorLine::VCenter:
+ QObject::connect(edge.item, SIGNAL(heightChanged()), q, SLOT(updateVerticalAnchors()));
+ break;
+ case QFxAnchorLine::Top: //no connection needed
+ default:
+ break;
+ }
+ } else if (edge.item->itemParent() == item->itemParent()) { //siblings
+ switch(edge.anchorLine) {
+ case QFxAnchorLine::Top:
+ QObject::connect(edge.item, SIGNAL(topChanged()), q, SLOT(updateVerticalAnchors()));
+ break;
+ case QFxAnchorLine::Bottom:
+ QObject::connect(edge.item, SIGNAL(bottomChanged()), q, SLOT(updateVerticalAnchors()));
+ break;
+ case QFxAnchorLine::VCenter:
+ QObject::connect(edge.item, SIGNAL(vcenterChanged()), q, SLOT(updateVerticalAnchors()));
+ break;
+ default:
+ break;
+ }
+ } else {
+ qmlInfo(item) << "Can't anchor to an item that isn't a parent or sibling.";
+ }
+}
+
+void QFxAnchors::connectVAnchors()
+{
+ Q_D(QFxAnchors);
+ if (!d->checkVValid())
+ return;
+
+ if (d->usedAnchors & HasTopAnchor) {
+ //Handle stretching connections (if we have multiple horizontal anchors)
+ QFxAnchorLine *edge = 0;
+ if (d->usedAnchors & HasBottomAnchor) {
+ edge = &d->bottom;
+ connect(this, SIGNAL(bottomMarginChanged()), this, SLOT(updateVerticalAnchors()));
+ } else if (d->usedAnchors & HasVCenterAnchor) {
+ edge = &d->vCenter;
+ connect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors()));
+ }
+ if (edge) {
+ //we need to stretch
+ d->connectVHelper(*edge);
+ }
+
+ //Handle top
+ d->connectVHelper(d->top);
+ connect(this, SIGNAL(topMarginChanged()), this, SLOT(updateVerticalAnchors()));
+ updateVerticalAnchors();
+ } else if (d->usedAnchors & HasBottomAnchor) {
+ //Handle stretching connections (if we have multiple horizontal anchors)
+ if (d->usedAnchors & HasVCenterAnchor) {
+ d->connectVHelper(d->vCenter);
+ connect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors()));
+ }
+
+ //Handle bottom
+ d->connectVHelper(d->bottom);
+ connect(this, SIGNAL(bottomMarginChanged()), this, SLOT(updateVerticalAnchors()));
+ updateVerticalAnchors();
+ } else if (d->usedAnchors & HasVCenterAnchor) {
+ //Handle vCenter
+ d->connectVHelper(d->vCenter);
+ connect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors()));
+ updateVerticalAnchors();
+ }
+}
+
+void QFxAnchorsPrivate::connectHHelper(const QFxAnchorLine &edge)
+{
+ //### should we do disconnects first? (will it be called more than once?)
+ Q_Q(QFxAnchors);
+ if (edge.item == item->itemParent()) { //child-parent
+ switch(edge.anchorLine) {
+ case QFxAnchorLine::Right:
+ case QFxAnchorLine::HCenter:
+ QObject::connect(edge.item, SIGNAL(widthChanged()), q, SLOT(updateHorizontalAnchors()));
+ break;
+ case QFxAnchorLine::Left: //no connection needed
+ default:
+ break;
+ }
+ } else if (edge.item->itemParent() == item->itemParent()) { //siblings
+ switch(edge.anchorLine) {
+ case QFxAnchorLine::Left:
+ QObject::connect(edge.item, SIGNAL(leftChanged()), q, SLOT(updateHorizontalAnchors()));
+ break;
+ case QFxAnchorLine::Right:
+ QObject::connect(edge.item, SIGNAL(rightChanged()), q, SLOT(updateHorizontalAnchors()));
+ break;
+ case QFxAnchorLine::HCenter:
+ QObject::connect(edge.item, SIGNAL(hcenterChanged()), q, SLOT(updateHorizontalAnchors()));
+ break;
+ default:
+ break;
+ }
+ } else {
+ qmlInfo(item) << "Can't anchor to an item that isn't a parent or sibling.";
+ }
+}
+
+void QFxAnchors::connectHAnchors()
+{
+ Q_D(QFxAnchors);
+ if (!d->checkHValid())
+ return;
+
+ if (d->usedAnchors & HasLeftAnchor) {
+ //Handle stretching connections (if we have multiple horizontal anchors)
+ QFxAnchorLine *edge = 0;
+ if (d->usedAnchors & HasRightAnchor) {
+ edge = &d->right;
+ connect(this, SIGNAL(rightMarginChanged()), this, SLOT(updateHorizontalAnchors()));
+ } else if (d->usedAnchors & HasHCenterAnchor) {
+ edge = &d->hCenter;
+ connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors()));
+ }
+ if (edge) {
+ //we need to stretch
+ d->connectHHelper(*edge);
+ }
+
+ //Handle left
+ d->connectHHelper(d->left);
+ connect(this, SIGNAL(leftMarginChanged()), this, SLOT(updateHorizontalAnchors()));
+ updateHorizontalAnchors();
+ } else if (d->usedAnchors & HasRightAnchor) {
+ //Handle stretching connections (if we have multiple horizontal anchors)
+ if (d->usedAnchors & HasHCenterAnchor) {
+ d->connectHHelper(d->hCenter);
+ connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors()));
+ }
+
+ //Handle right
+ d->connectHHelper(d->right);
+ connect(this, SIGNAL(rightMarginChanged()), this, SLOT(updateHorizontalAnchors()));
+ updateHorizontalAnchors();
+ } else if (d->usedAnchors & HasHCenterAnchor) {
+ //Handle hCenter
+ d->connectHHelper(d->hCenter);
+ connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors()));
+ updateHorizontalAnchors();
+ }
+}
+
+bool QFxAnchorsPrivate::calcStretch(const QFxAnchorLine &edge1,
+ const QFxAnchorLine &edge2,
+ int offset1,
+ int offset2,
+ QFxAnchorLine::AnchorLine line,
+ int &stretch)
+{
+ bool edge1IsParent = (edge1.item == item->itemParent());
+ bool edge2IsParent = (edge2.item == item->itemParent());
+ bool edge1IsSibling = (edge1.item->itemParent() == item->itemParent());
+ bool edge2IsSibling = (edge2.item->itemParent() == item->itemParent());
+
+ bool invalid = false;
+ if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
+ stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2)
+ - ((int)position(edge1.item, edge1.anchorLine) + offset1);
+ } else if (edge2IsParent && edge1IsSibling) {
+ stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2)
+ - ((int)position(item->itemParent(), line)
+ + (int)position(edge1.item, edge1.anchorLine) + offset1);
+ } else if (edge2IsSibling && edge1IsParent) {
+ stretch = ((int)position(item->itemParent(), line) + (int)position(edge2.item, edge2.anchorLine) + offset2)
+ - ((int)position(edge1.item, edge1.anchorLine) + offset1);
+ } else
+ invalid = true;
+
+ return invalid;
+}
+
+void QFxAnchors::updateVerticalAnchors()
+{
+ Q_D(QFxAnchors);
+ if (!d->updatingVerticalAnchor) {
+ d->updatingVerticalAnchor = true;
+ if (d->usedAnchors & HasTopAnchor) {
+ //Handle stretching
+ bool invalid = true;
+ int height = 0;
+ if (d->usedAnchors & HasBottomAnchor) {
+ invalid = d->calcStretch(d->top, d->bottom, d->topMargin, -d->bottomMargin, QFxAnchorLine::Top, height);
+ } else if (d->usedAnchors & HasVCenterAnchor) {
+ invalid = d->calcStretch(d->top, d->vCenter, d->topMargin, d->vCenterOffset, QFxAnchorLine::Top, height);
+ height *= 2;
+ }
+ if (!invalid)
+ d->item->setHeight(height);
+
+ //Handle top
+ if (d->top.item == d->item->itemParent()) {
+ d->item->setY(adjustedPosition(d->top.item, d->top.anchorLine) + d->topMargin);
+ } else if (d->top.item->itemParent() == d->item->itemParent()) {
+ d->item->setY(position(d->top.item, d->top.anchorLine) + d->topMargin);
+ }
+ } else if (d->usedAnchors & HasBottomAnchor) {
+ //Handle stretching (top + bottom case is handled above)
+ if (d->usedAnchors & HasVCenterAnchor) {
+ int height = 0;
+ bool invalid = d->calcStretch(d->vCenter, d->bottom, d->vCenterOffset, -d->bottomMargin,
+ QFxAnchorLine::Top, height);
+ if (!invalid)
+ d->item->setHeight(height*2);
+ }
+
+ //Handle bottom
+ if (d->bottom.item == d->item->itemParent()) {
+ d->item->setY(adjustedPosition(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin);
+ } else if (d->bottom.item->itemParent() == d->item->itemParent()) {
+ d->item->setY(position(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin);
+ }
+
+
+ } else if (d->usedAnchors & HasVCenterAnchor) {
+ //(stetching handled above)
+
+ //Handle vCenter
+ if (d->vCenter.item == d->item->itemParent()) {
+ d->item->setY(adjustedPosition(d->vCenter.item, d->vCenter.anchorLine)
+ - d->item->height()/2 + d->vCenterOffset);
+ } else if (d->vCenter.item->itemParent() == d->item->itemParent()) {
+ d->item->setY(position(d->vCenter.item, d->vCenter.anchorLine) - d->item->height()/2 + d->vCenterOffset);
+ }
+ }
+ d->updatingVerticalAnchor = false;
+ } else {
+ qmlInfo(d->item) << "Anchor loop detected on vertical anchor.";
+ }
+}
+
+void QFxAnchors::updateHorizontalAnchors()
+{
+ Q_D(QFxAnchors);
+ if (!d->updatingHorizontalAnchor) {
+ d->updatingHorizontalAnchor = true;
+
+ //alternate implementation (needs performance testing)
+ /*switch(d->usedAnchors & QFxAnchors::Horizontal_Mask) {
+ case 0x03: //(HasLeftAnchor | HasRightAnchor)
+ {
+ int width = 0;
+ if (!d->calcStretch(d->left, d->right, d->leftMargin, -d->rightMargin, QFxAnchorLine::Left, width))
+ d->item->setWidth(width);
+ //fall though
+ }
+ case 0x11: //(HasLeftAnchor | HasHCenterAnchor)
+ {
+ if (d->usedAnchors & HasHCenterAnchor) {
+ int width = 0;
+ if (!d->calcStretch(d->left, d->hCenter, d->leftMargin, d->hCenterOffset, QFxAnchorLine::Left, width))
+ d->item->setWidth(width*2);
+ }
+ //fall though
+ }
+ case HasLeftAnchor:
+ if (d->left.item == d->item->itemParent()) {
+ d->item->setX(adjustedPosition(d->left.item, d->left.anchorLine) + d->leftMargin);
+ } else if (d->left.item->itemParent() == d->item->itemParent()) {
+ d->item->setX(position(d->left.item, d->left.anchorLine) + d->leftMargin);
+ }
+ break;
+ case 0x12: //(HasRightAnchor | HasHCenterAnchor)
+ {
+ int width = 0;
+ if (!d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin, QFxAnchorLine::Left, width))
+ d->item->setWidth(width*2);
+ //fall though
+ }
+ case HasRightAnchor:
+ if (d->right.item == d->item->itemParent()) {
+ d->item->setX(adjustedPosition(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin);
+ } else if (d->right.item->itemParent() == d->item->itemParent()) {
+ d->item->setX(position(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin);
+ }
+ break;
+ case HasHCenterAnchor:
+ if (d->hCenter.item == d->item->itemParent()) {
+ d->item->setX(adjustedPosition(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset);
+ } else if (d->hCenter.item->itemParent() == d->item->itemParent()) {
+ d->item->setX(position(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset);
+ }
+ break;
+ default:
+ break;
+ }*/
+
+ if (d->usedAnchors & HasLeftAnchor) {
+ //Handle stretching
+ bool invalid = true;
+ int width = 0;
+ if (d->usedAnchors & HasRightAnchor) {
+ invalid = d->calcStretch(d->left, d->right, d->leftMargin, -d->rightMargin, QFxAnchorLine::Left, width);
+ } else if (d->usedAnchors & HasHCenterAnchor) {
+ invalid = d->calcStretch(d->left, d->hCenter, d->leftMargin, d->hCenterOffset, QFxAnchorLine::Left, width);
+ width *= 2;
+ }
+ if (!invalid)
+ d->item->setWidth(width);
+
+ //Handle left
+ if (d->left.item == d->item->itemParent()) {
+ d->item->setX(adjustedPosition(d->left.item, d->left.anchorLine) + d->leftMargin);
+ } else if (d->left.item->itemParent() == d->item->itemParent()) {
+ d->item->setX(position(d->left.item, d->left.anchorLine) + d->leftMargin);
+ }
+ } else if (d->usedAnchors & HasRightAnchor) {
+ //Handle stretching (left + right case is handled in updateLeftAnchor)
+ if (d->usedAnchors & HasHCenterAnchor) {
+ int width = 0;
+ bool invalid = d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin,
+ QFxAnchorLine::Left, width);
+ if (!invalid)
+ d->item->setWidth(width*2);
+ }
+
+ //Handle right
+ if (d->right.item == d->item->itemParent()) {
+ d->item->setX(adjustedPosition(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin);
+ } else if (d->right.item->itemParent() == d->item->itemParent()) {
+ d->item->setX(position(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin);
+ }
+ } else if (d->usedAnchors & HasHCenterAnchor) {
+ //Handle hCenter
+ if (d->hCenter.item == d->item->itemParent()) {
+ d->item->setX(adjustedPosition(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset);
+ } else if (d->hCenter.item->itemParent() == d->item->itemParent()) {
+ d->item->setX(position(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset);
+ }
+ }
+
+ d->updatingHorizontalAnchor = false;
+ } else {
+ qmlInfo(d->item) << "Anchor loop detected on horizontal anchor.";
+ }
+}
+
+QFxAnchorLine QFxAnchors::top() const
+{
+ Q_D(const QFxAnchors);
+ return d->top;
+}
+
+void QFxAnchors::setTop(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkVAnchorValid(edge))
+ return;
+
+ d->usedAnchors |= HasTopAnchor;
+
+ d->checkVValid();
+
+ d->top = edge;
+}
+
+void QFxAnchors::resetTop()
+{
+ Q_D(QFxAnchors);
+
+ //update flags
+ d->usedAnchors &= ~HasTopAnchor;
+
+ //clear binding
+ QmlMetaProperty prop(this, "top");
+ prop.binding()->clearExpression();
+
+ //disconnect signal/slot connections as needed
+ disconnect(this, SIGNAL(topMarginChanged()), this, SLOT(updateVerticalAnchors()));
+ disconnect(d->top.item, 0, this, 0);
+
+ updateVerticalAnchors();
+}
+
+QFxAnchorLine QFxAnchors::bottom() const
+{
+ Q_D(const QFxAnchors);
+ return d->bottom;
+}
+
+void QFxAnchors::setBottom(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkVAnchorValid(edge))
+ return;
+
+ d->usedAnchors |= HasBottomAnchor;
+
+ d->checkVValid();
+
+ d->bottom = edge;
+}
+
+void QFxAnchors::resetBottom()
+{
+ Q_D(QFxAnchors);
+
+ //update flags
+ d->usedAnchors &= ~HasBottomAnchor;
+
+ //clear binding
+ QmlMetaProperty prop(this, "bottom");
+ prop.binding()->clearExpression();
+
+ //disconnect signal/slot connections as needed
+ disconnect(this, SIGNAL(bottomMarginChanged()), this, SLOT(updateVerticalAnchors()));
+ disconnect(d->bottom.item, 0, this, 0);
+
+ updateVerticalAnchors();
+}
+
+QFxAnchorLine QFxAnchors::verticalCenter() const
+{
+ Q_D(const QFxAnchors);
+ return d->vCenter;
+}
+
+void QFxAnchors::setVerticalCenter(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkVAnchorValid(edge))
+ return;
+
+ d->usedAnchors |= HasVCenterAnchor;
+
+ d->checkVValid();
+
+ d->vCenter = edge;
+}
+
+void QFxAnchors::resetVerticalCenter()
+{
+ Q_D(QFxAnchors);
+
+ //update flags
+ d->usedAnchors &= ~HasVCenterAnchor;
+
+ //clear binding
+ QmlMetaProperty prop(this, "verticalCenter");
+ prop.binding()->clearExpression();
+
+ //disconnect signal/slot connections as needed
+ disconnect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors()));
+ disconnect(d->vCenter.item, 0, this, 0);
+
+ updateVerticalAnchors();
+}
+
+QFxAnchorLine QFxAnchors::left() const
+{
+ Q_D(const QFxAnchors);
+ return d->left;
+}
+
+void QFxAnchors::setLeft(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkHAnchorValid(edge))
+ return;
+
+ d->usedAnchors |= HasLeftAnchor;
+
+ d->checkHValid();
+
+ d->left = edge;
+}
+
+void QFxAnchors::resetLeft()
+{
+ Q_D(QFxAnchors);
+
+ //update flags
+ d->usedAnchors &= ~HasLeftAnchor;
+
+ //clear binding
+ QmlMetaProperty prop(this, "left");
+ prop.binding()->clearExpression();
+
+ //disconnect signal/slot connections as needed
+ disconnect(this, SIGNAL(leftMarginChanged()), this, SLOT(updateHorizontalAnchors()));
+ disconnect(d->left.item, 0, this, 0);
+
+ updateHorizontalAnchors();
+}
+
+QFxAnchorLine QFxAnchors::right() const
+{
+ Q_D(const QFxAnchors);
+ return d->right;
+}
+
+void QFxAnchors::setRight(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkHAnchorValid(edge))
+ return;
+
+ d->usedAnchors |= HasRightAnchor;
+
+ d->checkHValid();
+
+ d->right = edge;
+}
+
+void QFxAnchors::resetRight()
+{
+ Q_D(QFxAnchors);
+
+ //update flags
+ d->usedAnchors &= ~HasRightAnchor;
+
+ //clear binding
+ QmlMetaProperty prop(this, "right");
+ prop.binding()->clearExpression();
+
+ //disconnect signal/slot connections as needed
+ disconnect(this, SIGNAL(rightMarginChanged()), this, SLOT(updateHorizontalAnchors()));
+ disconnect(d->right.item, 0, this, 0);
+
+ updateHorizontalAnchors();
+}
+
+QFxAnchorLine QFxAnchors::horizontalCenter() const
+{
+ Q_D(const QFxAnchors);
+ return d->hCenter;
+}
+
+void QFxAnchors::setHorizontalCenter(const QFxAnchorLine &edge)
+{
+ Q_D(QFxAnchors);
+ if (!d->checkHAnchorValid(edge))
+ return;
+
+ d->usedAnchors |= HasHCenterAnchor;
+
+ d->checkHValid();
+
+ d->hCenter = edge;
+}
+
+void QFxAnchors::resetHorizontalCenter()
+{
+ Q_D(QFxAnchors);
+
+ //update flags
+ d->usedAnchors &= ~HasHCenterAnchor;
+
+ //clear binding
+ QmlMetaProperty prop(this, "horizontalCenter");
+ prop.binding()->clearExpression();
+
+ //disconnect signal/slot connections as needed
+ disconnect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors()));
+ disconnect(d->hCenter.item, 0, this, 0);
+
+ updateHorizontalAnchors();
+}
+
+int QFxAnchors::leftMargin() const
+{
+ Q_D(const QFxAnchors);
+ return d->leftMargin;
+}
+
+void QFxAnchors::setLeftMargin(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->leftMargin == offset)
+ return;
+ d->leftMargin = offset;
+ emit leftMarginChanged();
+}
+
+int QFxAnchors::rightMargin() const
+{
+ Q_D(const QFxAnchors);
+ return d->rightMargin;
+}
+
+void QFxAnchors::setRightMargin(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->rightMargin == offset)
+ return;
+ d->rightMargin = offset;
+ emit rightMarginChanged();
+}
+
+int QFxAnchors::horizontalCenterOffset() const
+{
+ Q_D(const QFxAnchors);
+ return d->hCenterOffset;
+}
+
+void QFxAnchors::setHorizontalCenterOffset(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->hCenterOffset == offset)
+ return;
+ d->hCenterOffset = offset;
+ emit horizontalCenterOffsetChanged();
+}
+
+int QFxAnchors::topMargin() const
+{
+ Q_D(const QFxAnchors);
+ return d->topMargin;
+}
+
+void QFxAnchors::setTopMargin(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->topMargin == offset)
+ return;
+ d->topMargin = offset;
+ emit topMarginChanged();
+}
+
+int QFxAnchors::bottomMargin() const
+{
+ Q_D(const QFxAnchors);
+ return d->bottomMargin;
+}
+
+void QFxAnchors::setBottomMargin(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->bottomMargin == offset)
+ return;
+ d->bottomMargin = offset;
+ emit bottomMarginChanged();
+}
+
+int QFxAnchors::verticalCenterOffset() const
+{
+ Q_D(const QFxAnchors);
+ return d->vCenterOffset;
+}
+
+void QFxAnchors::setVerticalCenterOffset(int offset)
+{
+ Q_D(QFxAnchors);
+ if (d->vCenterOffset == offset)
+ return;
+ d->vCenterOffset = offset;
+ emit verticalCenterOffsetChanged();
+}
+
+#if 0
+/*!
+ \property QFxAnchors::baseline
+ \brief what the baseline of the item should be anchored to (aligned with).
+
+ The baseline of a Text item is the imaginary line on which the text sits. Controls containing
+ text usually set their baseline to the baseline of their text.
+
+ For non-text items, a default baseline offset of two-thirds of the item's height is used
+ to determine the baseline.
+*/
+int QFxAnchors::baseline() const
+{
+ return d->item->baseline();
+}
+
+void QFxAnchors::setBaseline(int baseline)
+{
+ d->usedAnchors |= HasBaselineAnchor;
+
+ if (d->usedAnchors & HasTopAnchor && d->usedAnchors & HasBottomAnchor) {
+ qmlInfo(d->item) << "Can't specify top, bottom, and baseline anchors";
+ return;
+ }
+
+ if (d->usedAnchors & HasTopAnchor) {
+ int hoffset = baseline - d->item->baseline();
+ d->item->setHeight(d->item->height() + hoffset);
+ } else {
+ if (d->usedAnchors & HasBottomAnchor) {
+ int hoffset = d->item->baseline() - baseline;
+ d->item->setHeight(d->item->height() + hoffset);
+ }
+
+ int boffset = d->item->baseline() - d->item->top();
+ QFxItem *parentItem = d->item->itemParent();
+ if (parentItem)
+ d->item->setY(baseline - boffset - parentItem->top());
+ else
+ d->item->setY(baseline - boffset);
+ }
+}
+#endif
+
+QFxAnchors::UsedAnchors QFxAnchors::usedAnchors() const
+{
+ Q_D(const QFxAnchors);
+ return d->usedAnchors;
+}
+
+void QFxAnchors::setItem(QFxItem *item)
+{
+ Q_D(QFxAnchors);
+ d->item = item;
+}
+
+bool QFxAnchorsPrivate::checkHValid() const
+{
+ if (usedAnchors & QFxAnchors::HasLeftAnchor &&
+ usedAnchors & QFxAnchors::HasRightAnchor &&
+ usedAnchors & QFxAnchors::HasHCenterAnchor) {
+ qmlInfo(item) << "Can't specify left, right, and hcenter anchors";
+ return false;
+ }
+
+ return true;
+}
+
+bool QFxAnchorsPrivate::checkHAnchorValid(QFxAnchorLine anchor) const
+{
+ if (anchor.anchorLine & QFxAnchorLine::Vertical_Mask) {
+ qmlInfo(item) << "Can't anchor a horizontal edge to a vertical edge.";
+ return false;
+ }else if (anchor.item == item){
+ qmlInfo(item) << "Can't anchor item to self.";
+ return false;
+ }
+
+ return true;
+}
+
+bool QFxAnchorsPrivate::checkVValid() const
+{
+ if (usedAnchors & QFxAnchors::HasTopAnchor &&
+ usedAnchors & QFxAnchors::HasBottomAnchor &&
+ usedAnchors & QFxAnchors::HasVCenterAnchor) {
+ qmlInfo(item) << "Can't specify top, bottom, and vcenter anchors";
+ return false;
+ }
+
+ return true;
+}
+
+bool QFxAnchorsPrivate::checkVAnchorValid(QFxAnchorLine anchor) const
+{
+ if (anchor.anchorLine & QFxAnchorLine::Horizontal_Mask) {
+ qmlInfo(item) << "Can't anchor a vertical edge to a horizontal edge.";
+ return false;
+ }else if (anchor.item == item){
+ qmlInfo(item) << "Can't anchor item to self.";
+ return false;
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxanchors.h b/src/declarative/fx/qfxanchors.h
new file mode 100644
index 0000000..5a8cc1a
--- /dev/null
+++ b/src/declarative/fx/qfxanchors.h
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXANCHORS_H
+#define QFXANCHORS_H
+
+#include <qfxglobal.h>
+#include <QObject>
+#include <qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxItem;
+class QFxAnchorsPrivate;
+
+class QFxAnchorLine
+{
+public:
+ QFxAnchorLine() : item(0), anchorLine(Left)
+ {
+ }
+
+ enum AnchorLine {
+ 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
+ };
+
+ QFxItem *item;
+ AnchorLine anchorLine;
+};
+
+Q_DECLARE_METATYPE(QFxAnchorLine);
+
+class Q_DECLARATIVE_EXPORT QFxAnchors : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QFxAnchorLine left READ left WRITE setLeft RESET resetLeft);
+ Q_PROPERTY(QFxAnchorLine right READ right WRITE setRight RESET resetRight);
+ Q_PROPERTY(QFxAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter);
+ Q_PROPERTY(QFxAnchorLine top READ top WRITE setTop RESET resetTop);
+ Q_PROPERTY(QFxAnchorLine bottom READ bottom WRITE setBottom RESET resetBottom);
+ Q_PROPERTY(QFxAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter);
+ Q_PROPERTY(int leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged);
+ Q_PROPERTY(int rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged);
+ Q_PROPERTY(int horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged());
+ Q_PROPERTY(int topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged);
+ Q_PROPERTY(int bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged);
+ Q_PROPERTY(int verticalCenterOffset READ verticalCenterOffset WRITE setVerticalCenterOffset NOTIFY verticalCenterOffsetChanged());
+ Q_PROPERTY(QFxItem *fill READ fill WRITE setFill);
+ Q_PROPERTY(QFxItem *centeredIn READ centeredIn WRITE setCenteredIn);
+
+public:
+ QFxAnchors(QObject *parent=0);
+
+ enum UsedAnchor {
+ HasLeftAnchor = 0x01,
+ HasRightAnchor = 0x02,
+ HasTopAnchor = 0x04,
+ HasBottomAnchor = 0x08,
+ HasHCenterAnchor = 0x10,
+ HasVCenterAnchor = 0x20,
+ HasBaselineAnchor = 0x40,
+ Horizontal_Mask = HasLeftAnchor | HasRightAnchor | HasHCenterAnchor,
+ Vertical_Mask = HasTopAnchor | HasBottomAnchor | HasVCenterAnchor | HasBaselineAnchor
+ };
+ Q_DECLARE_FLAGS(UsedAnchors, UsedAnchor);
+
+ QFxAnchorLine left() const;
+ void setLeft(const QFxAnchorLine &edge);
+ Q_INVOKABLE void resetLeft(); //### temporarily invokable for testing
+
+ QFxAnchorLine right() const;
+ void setRight(const QFxAnchorLine &edge);
+ void resetRight();
+
+ QFxAnchorLine horizontalCenter() const;
+ void setHorizontalCenter(const QFxAnchorLine &edge);
+ void resetHorizontalCenter();
+
+ QFxAnchorLine top() const;
+ void setTop(const QFxAnchorLine &edge);
+ void resetTop();
+
+ QFxAnchorLine bottom() const;
+ void setBottom(const QFxAnchorLine &edge);
+ void resetBottom();
+
+ QFxAnchorLine verticalCenter() const;
+ void setVerticalCenter(const QFxAnchorLine &edge);
+ void resetVerticalCenter();
+
+ int leftMargin() const;
+ void setLeftMargin(int);
+
+ int rightMargin() const;
+ void setRightMargin(int);
+
+ int horizontalCenterOffset() const;
+ void setHorizontalCenterOffset(int);
+
+ int topMargin() const;
+ void setTopMargin(int);
+
+ int bottomMargin() const;
+ void setBottomMargin(int);
+
+ int verticalCenterOffset() const;
+ void setVerticalCenterOffset(int);
+
+ QFxItem *fill() const;
+ void setFill(QFxItem *);
+
+ QFxItem *centeredIn() const;
+ void setCenteredIn(QFxItem *);
+
+ UsedAnchors usedAnchors() const;
+
+ void setItem(QFxItem *item);
+
+ void connectHAnchors();
+ void connectVAnchors();
+
+Q_SIGNALS:
+ void leftMarginChanged();
+ void rightMarginChanged();
+ void topMarginChanged();
+ void bottomMarginChanged();
+ void verticalCenterOffsetChanged();
+ void horizontalCenterOffsetChanged();
+
+private Q_SLOTS:
+ void fillChanged();
+ void updateHorizontalAnchors();
+ void updateVerticalAnchors();
+
+private:
+ //### should item be a friend? (and make some of the public methods private or protected)
+ Q_DISABLE_COPY(QFxAnchors)
+ Q_DECLARE_PRIVATE(QFxAnchors)
+};
+
+QML_DECLARE_TYPE(QFxAnchors);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxanchors_p.h b/src/declarative/fx/qfxanchors_p.h
new file mode 100644
index 0000000..82c2086
--- /dev/null
+++ b/src/declarative/fx/qfxanchors_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXANCHORS_P_H
+#define QFXANCHORS_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 "qfxanchors.h"
+#include "private/qobject_p.h"
+
+
+QT_BEGIN_NAMESPACE
+class QFxAnchorsPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QFxAnchors)
+public:
+ QFxAnchorsPrivate()
+ : item(0), usedAnchors(0), fill(0), centeredIn(0), leftMargin(0), rightMargin(0),
+ topMargin(0), bottomMargin(0), vCenterOffset(0), hCenterOffset(0),
+ updatingHorizontalAnchor(false), updatingVerticalAnchor(false)
+ {
+ }
+
+ void init()
+ {
+ }
+
+ bool checkHValid() const;
+ bool checkVValid() const;
+ bool checkHAnchorValid(QFxAnchorLine anchor) const;
+ bool checkVAnchorValid(QFxAnchorLine anchor) const;
+ void connectHHelper(const QFxAnchorLine &anchorLine);
+ void connectVHelper(const QFxAnchorLine &anchorLine);
+ bool calcStretch(const QFxAnchorLine &edge1, const QFxAnchorLine &edge2, int offset1, int offset2, QFxAnchorLine::AnchorLine line, int &stretch);
+
+ QFxItem *item;
+ QFxAnchors::UsedAnchors usedAnchors;
+
+ QFxItem *fill;
+ QFxItem *centeredIn;
+
+ QFxAnchorLine left;
+ QFxAnchorLine right;
+ QFxAnchorLine top;
+ QFxAnchorLine bottom;
+ QFxAnchorLine vCenter;
+ QFxAnchorLine hCenter;
+
+ int leftMargin;
+ int rightMargin;
+ int topMargin;
+ int bottomMargin;
+ int vCenterOffset;
+ int hCenterOffset;
+
+ bool updatingHorizontalAnchor;
+ bool updatingVerticalAnchor;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/fx/qfxanimatedimageitem.cpp b/src/declarative/fx/qfxanimatedimageitem.cpp
new file mode 100644
index 0000000..7a1cb7f
--- /dev/null
+++ b/src/declarative/fx/qfxanimatedimageitem.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QMovie>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlengine.h>
+#include "qfxanimatedimageitem.h"
+#include "qfxanimatedimageitem_p.h"
+#include <QNetworkRequest>
+#include <QNetworkReply>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QFxAnimatedImageItem
+ \internal
+*/
+
+/*!
+ \qmlclass AnimatedImage
+ \inherits Image
+
+ This item provides for playing animations stored as images containing a series of frames,
+ such as GIF files. The full list of supported formats can be determined with
+ QMovie::supportedFormats().
+
+ \table
+ \row
+ \o \image animatedimageitem.gif
+ \o
+ \qml
+Item {
+ width: anim.width; height: anim.height+8
+ AnimatedImage { id: anim; source: "pics/games-anim.gif" }
+ Rect { color: "red"; width: 4; height: 8; y: anim.height
+ x: (anim.width-width)*anim.currentFrame/(anim.frameCount-1)
+ }
+}
+ \endqml
+ \endtable
+*/
+QML_DEFINE_TYPE(QFxAnimatedImageItem, AnimatedImage);
+
+QFxAnimatedImageItem::QFxAnimatedImageItem(QFxItem *parent)
+ : QFxImage(*(new QFxAnimatedImageItemPrivate), parent)
+{
+}
+
+QFxAnimatedImageItem::QFxAnimatedImageItem(QFxAnimatedImageItemPrivate &dd, QFxItem *parent)
+ : QFxImage(dd, parent)
+{
+}
+
+QFxAnimatedImageItem::~QFxAnimatedImageItem()
+{
+ Q_D(QFxAnimatedImageItem);
+ delete d->_movie;
+}
+
+/*!
+ \qmlproperty bool AnimatedImage::playing
+ This property holds whether the animated image is playing or not
+
+ Defaults to true, so as to start playing immediately.
+*/
+bool QFxAnimatedImageItem::isPlaying() const
+{
+ Q_D(const QFxAnimatedImageItem);
+ if (!d->_movie)
+ return false;
+ return d->_movie->state()==QMovie::Running;
+}
+
+void QFxAnimatedImageItem::setPlaying(bool play)
+{
+ Q_D(QFxAnimatedImageItem);
+ 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. Watching when this changes can
+ allow other things to animate at the same time as the image. frameCount is the number
+ of frames in the animation. For some animation formats, frameCount is unknown and set to zero.
+*/
+int QFxAnimatedImageItem::currentFrame() const
+{
+ Q_D(const QFxAnimatedImageItem);
+ if (!d->_movie)
+ return -1;
+ return d->_movie->currentFrameNumber();
+}
+
+void QFxAnimatedImageItem::setCurrentFrame(int frame)
+{
+ Q_D(QFxAnimatedImageItem);
+ if (!d->_movie)
+ return;
+ d->_movie->jumpToFrame(frame);
+}
+
+int QFxAnimatedImageItem::frameCount() const
+{
+ Q_D(const QFxAnimatedImageItem);
+ if (!d->_movie)
+ return 0;
+ return d->_movie->frameCount();
+}
+
+void QFxAnimatedImageItem::setSource(const QString &url)
+{
+ Q_D(QFxAnimatedImageItem);
+ if (url == d->source)
+ return;
+
+ delete d->_movie;
+ d->_movie = 0;
+
+ if (d->reply) {
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+
+ d->source = url;
+ d->url = qmlContext(this)->resolvedUrl(url);
+
+ if (url.isEmpty()) {
+ delete d->_movie;
+ d->status = Idle;
+ } else {
+ d->status = Loading;
+ QNetworkRequest req(d->url);
+ req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+ d->reply = qmlContext(this)->engine()->networkAccessManager()->get(req);
+ QObject::connect(d->reply, SIGNAL(finished()),
+ this, SLOT(movieRequestFinished()));
+ }
+
+ emit statusChanged(d->status);
+}
+
+void QFxAnimatedImageItem::movieRequestFinished()
+{
+ Q_D(QFxAnimatedImageItem);
+ d->_movie = new QMovie(d->reply);
+ if (!d->_movie->isValid()){
+ qWarning() << "Error Reading File " << d->url;
+ delete d->_movie;
+ d->_movie = 0;
+ return;
+ }
+ connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
+ this, SIGNAL(playingChanged()));
+ connect(d->_movie, SIGNAL(frameChanged(int)),
+ this, SLOT(movieUpdate()));
+ d->_movie->setCacheMode(QMovie::CacheAll);
+ d->_movie->start();
+ setPixmap(d->_movie->currentPixmap());
+}
+
+void QFxAnimatedImageItem::movieUpdate()
+{
+ Q_D(QFxAnimatedImageItem);
+ setPixmap(d->_movie->currentPixmap());
+ emit frameChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxanimatedimageitem.h b/src/declarative/fx/qfxanimatedimageitem.h
new file mode 100644
index 0000000..121fe62
--- /dev/null
+++ b/src/declarative/fx/qfxanimatedimageitem.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXANIMATEDIMAGEITEM_H
+#define QFXANIMATEDIMAGEITEM_H
+
+#include <qfximage.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QMovie;
+class QFxAnimatedImageItemPrivate;
+
+class Q_DECLARATIVE_EXPORT QFxAnimatedImageItem : public QFxImage
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged)
+ Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY frameChanged)
+ Q_PROPERTY(int frameCount READ frameCount)
+public:
+ QFxAnimatedImageItem(QFxItem *parent=0);
+ ~QFxAnimatedImageItem();
+
+ bool isPlaying() const;
+ void setPlaying(bool play);
+
+ int currentFrame() const;
+ void setCurrentFrame(int frame);
+
+ int frameCount() const;
+
+ // Extends QFxImage's src property*/
+ virtual void setSource(const QString&);
+
+Q_SIGNALS:
+ void playingChanged();
+ void frameChanged();
+
+private Q_SLOTS:
+ void movieUpdate();
+ void movieRequestFinished();
+
+protected:
+ QFxAnimatedImageItem(QFxAnimatedImageItemPrivate &dd, QFxItem *parent);
+
+private:
+ Q_DISABLE_COPY(QFxAnimatedImageItem)
+ Q_DECLARE_PRIVATE(QFxAnimatedImageItem)
+};
+
+QML_DECLARE_TYPE(QFxAnimatedImageItem);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxanimatedimageitem_p.h b/src/declarative/fx/qfxanimatedimageitem_p.h
new file mode 100644
index 0000000..cb5da63
--- /dev/null
+++ b/src/declarative/fx/qfxanimatedimageitem_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXANIMATEDIMAGE_P_H
+#define QFXANIMATEDIMAGE_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 "qfximage_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMovie;
+
+class QFxAnimatedImageItemPrivate : public QFxImagePrivate
+{
+ Q_DECLARE_PUBLIC(QFxAnimatedImageItem)
+
+public:
+ QFxAnimatedImageItemPrivate()
+ : _movie(0)
+ {
+ }
+
+ QMovie *_movie;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFXANIMATEDIMAGE_P_H
diff --git a/src/declarative/fx/qfxblendedimage.cpp b/src/declarative/fx/qfxblendedimage.cpp
new file mode 100644
index 0000000..79b8e41
--- /dev/null
+++ b/src/declarative/fx/qfxblendedimage.cpp
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxblendedimage.h"
+#include <QtDeclarative/qmlcontext.h>
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glbasicshaders.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass BlendedImage
+ \brief The BlendedImage elements blends two different images depending on a blend ratio.
+
+ This element can be used to simulate blur on slow devices by setting secondaryUrl with
+ a pre-rendered blurred version of primaryUrl.
+
+ Note that this class will only work under OpenGL. On the software canvas it will display
+ only the primary image unless the blend is > 0.75, in which case it will display only the
+ secondary image.
+*/
+
+/*!
+ \internal
+ \class QFxBlendedImage
+ \brief The QFxBlendedImage blends two different images depending on a blend ratio.
+
+ This class can be used to simulate blur on slow devices by setting secondaryUrl with
+ a pre-rendered blurred version of primaryUrl.
+
+ Note that this class will only work under OpenGL. On the software canvas it will display
+ only the primary image unless the blend is > 0.75, in which case it will display only the
+ secondary image.
+*/
+QFxBlendedImage::QFxBlendedImage(QFxItem *parent)
+: QFxItem(parent), _blend(0), _smooth(false), dirty(false)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ setOptions(HasContents);
+#endif
+}
+
+/*!
+ \qmlproperty string BlendedImage::primaryUrl
+ The URL of the first image to be displayed in this item.
+*/
+QString QFxBlendedImage::primaryUrl() const
+{
+ return primSrc;
+}
+
+void QFxBlendedImage::primaryLoaded()
+{
+ primPix = QFxPixmap(primUrl);
+ dirty = true;
+ update();
+}
+
+void QFxBlendedImage::setPrimaryUrl(const QString &url)
+{
+ if (primSrc == url)
+ return;
+ if (!primSrc.isEmpty())
+ QFxPixmap::cancelGet(primUrl,this);
+ primSrc = url;
+ primUrl = qmlContext(this)->resolvedUrl(url);
+ if (!primSrc.isEmpty())
+ QFxPixmap::get(qmlEngine(this), primUrl,this,SLOT(primaryLoaded()));
+}
+
+/*!
+ \qmlproperty string BlendedImage::secondaryUrl
+ The URL of the second image to be displayed in this item.
+*/
+QString QFxBlendedImage::secondaryUrl() const
+{
+ return secSrc;
+}
+
+void QFxBlendedImage::secondaryLoaded()
+{
+ secPix = QFxPixmap(secUrl);
+ dirty = true;
+ update();
+}
+
+void QFxBlendedImage::setSecondaryUrl(const QString &url)
+{
+ if (secSrc == url)
+ return;
+ if (!secSrc.isEmpty())
+ QFxPixmap::cancelGet(secUrl,this);
+ secSrc = url;
+ secUrl = qmlContext(this)->resolvedUrl(url);
+ if (!secSrc.isEmpty())
+ QFxPixmap::get(qmlEngine(this), secUrl,this,SLOT(secondaryLoaded()));
+}
+
+/*!
+ \qmlproperty real BlendedImage::blend
+ The ratio used to blend the two images.
+
+ If blend has a value of 0, only the first image will be displayed.
+ If blend has a value of 1, only the second image will be displayed.
+*/
+qreal QFxBlendedImage::blend() const
+{
+ return _blend;
+}
+
+void QFxBlendedImage::setBlend(qreal b)
+{
+ _blend = b;
+ update();
+}
+
+/*!
+ \qmlproperty bool BlendedImage::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 BlendedImage is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the image is stationary on
+ the screen. A common pattern when animating an image is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+ */
+bool QFxBlendedImage::smoothTransform() const
+{
+ return _smooth;
+}
+
+void QFxBlendedImage::setSmoothTransform(bool s)
+{
+ if (_smooth == s)
+ return;
+ _smooth = s;
+ update();
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+
+void QFxBlendedImage::paintContents(QPainter &p)
+{
+ if (primSrc.isNull() && secSrc.isNull())
+ return;
+
+ if (_smooth) {
+ p.save();
+ p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, _smooth);
+ }
+
+ if (_blend < 0.75)
+ p.drawImage(0, 0, primPix);
+ else
+ p.drawImage(0, 0, secPix);
+
+ if (_smooth) {
+ p.restore();
+ }
+}
+
+#elif defined(QFX_RENDER_OPENGL2)
+
+void QFxBlendedImage::paintGLContents(GLPainter &p)
+{
+ static DualTextureBlendShader *shader = 0;
+ if (!shader)
+ shader = new DualTextureBlendShader();
+
+ if (dirty) {
+ prim.clear();
+ sec.clear();
+ prim.setImage(primPix);
+ sec.setImage(secPix);
+
+ dirty = false;
+ }
+
+ if (prim.isNull() || sec.isNull()) {
+
+ return;
+ }
+
+ GLfloat vertices[8];
+ GLfloat texVertices[8];
+
+ float widthV = width();
+ float heightV = height();
+ if (!widthV)
+ widthV = qMax(primPix.width(), secPix.width());
+ if (!heightV)
+ heightV = qMax(primPix.height(), secPix.height());
+
+ vertices[0] = 0; vertices[1] = heightV;
+ vertices[2] = widthV; vertices[3] = heightV;
+ vertices[4] = 0; vertices[5] = 0;
+ vertices[6] = widthV; vertices[7] = 0;
+
+ texVertices[0] = 0; texVertices[1] = 0;
+ texVertices[2] = 1; texVertices[3] = 0;
+ texVertices[4] = 0; texVertices[5] = 1;
+ texVertices[6] = 1; texVertices[7] = 1;
+
+ if (_blend == 0 || _blend == 1) {
+ QGLShaderProgram *tshader = p.useTextureShader();
+
+ GLTexture *tex = 0;
+
+ if (_blend == 0)
+ tex = &prim;
+ else
+ tex = &sec;
+
+ tshader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2);
+ tshader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2);
+
+ glBindTexture(GL_TEXTURE_2D, tex->texture());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ tshader->disableAttributeArray(SingleTextureShader::Vertices);
+ tshader->disableAttributeArray(SingleTextureShader::TextureCoords);
+ } else {
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, prim.texture());
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, sec.texture());
+
+ shader->enable();
+ shader->setOpacity(1);
+ qreal b = _blend;
+ if (b > 1) b = 1;
+ else if (b < 0) b = 0;
+ shader->setBlend(b);
+ shader->setTransform(p.activeTransform);
+
+ shader->setAttributeArray(DualTextureBlendShader::Vertices, vertices, 2);
+ shader->setAttributeArray(DualTextureBlendShader::TextureCoords, texVertices, 2);
+ shader->setAttributeArray(DualTextureBlendShader::BlendTextureCoords, texVertices, 2);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(DualTextureBlendShader::Vertices);
+ shader->disableAttributeArray(DualTextureBlendShader::TextureCoords);
+ shader->disableAttributeArray(DualTextureBlendShader::BlendTextureCoords);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glActiveTexture(GL_TEXTURE0);
+ }
+}
+#endif
+
+QML_DEFINE_TYPE(QFxBlendedImage,BlendedImage);
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxblendedimage.h b/src/declarative/fx/qfxblendedimage.h
new file mode 100644
index 0000000..5cc0238
--- /dev/null
+++ b/src/declarative/fx/qfxblendedimage.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXBLENDEDIMAGE_H
+#define QFXBLENDEDIMAGE_H
+
+#include <qfxitem.h>
+#if defined(QFX_RENDER_OPENGL2)
+#include <gltexture.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QFxBlendedImage : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString primaryUrl READ primaryUrl WRITE setPrimaryUrl)
+ Q_PROPERTY(QString secondaryUrl READ secondaryUrl WRITE setSecondaryUrl)
+ Q_PROPERTY(qreal blend READ blend WRITE setBlend)
+ Q_PROPERTY(bool smooth READ smoothTransform WRITE setSmoothTransform)
+public:
+ QFxBlendedImage(QFxItem *parent=0);
+
+ QString primaryUrl() const;
+ void setPrimaryUrl(const QString &);
+
+ QString secondaryUrl() const;
+ void setSecondaryUrl(const QString &);
+
+ qreal blend() const;
+ void setBlend(qreal);
+
+ bool smoothTransform() const;
+ void setSmoothTransform(bool);
+
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &painter);
+#elif defined(QFX_RENDER_OPENGL2)
+ void paintGLContents(GLPainter &);
+#endif
+
+private Q_SLOTS:
+ void primaryLoaded();
+ void secondaryLoaded();
+
+private:
+ QString primSrc;
+ QString secSrc;
+ QUrl primUrl;
+ QUrl secUrl;
+
+ qreal _blend;
+ bool _smooth;
+ bool dirty;
+#if defined(QFX_RENDER_OPENGL2)
+ GLTexture prim;
+ GLTexture sec;
+#endif
+ QFxPixmap primPix;
+ QFxPixmap secPix;
+};
+QML_DECLARE_TYPE(QFxBlendedImage);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXBLENDEDIMAGE_H
diff --git a/src/declarative/fx/qfxblurfilter.cpp b/src/declarative/fx/qfxblurfilter.cpp
new file mode 100644
index 0000000..baa2253
--- /dev/null
+++ b/src/declarative/fx/qfxblurfilter.cpp
@@ -0,0 +1,467 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxblurfilter.h"
+#include <private/qsimplecanvasitem_p.h>
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glsave.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#include <glbasicshaders.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+class QFxBlurFilterPrivate
+{
+public:
+ QFxBlurFilterPrivate()
+ : radius(0)
+ {
+ }
+ qreal radius;
+};
+
+/*!
+ \qmlclass Blur
+ \brief The Blur filter blurs an item and its contents.
+ \inherits Filter
+
+ Blurring reduces the clarity of a visual item. The following example
+ shows an icon at a blur radius of 0, 5 and 10.
+
+ \table
+ \row
+ \o
+ \qml
+HorizontalLayout {
+ Image {
+ source: "icon.png"
+ filter: Blur { radius: 0 }
+ }
+ Image {
+ source: "icon.png"
+ filter: Blur { radius: 5 }
+ }
+ Image {
+ source: "icon.png"
+ filter: Blur { radius: 10 }
+ }
+}
+ \endqml
+ \row
+ \o \image blur_example.png
+ \endtable
+
+ Bluring is only supported when Qt Declarative is compiled for OpenGL ES 2.0.
+ Otherwise the Blur filter has no effect.
+ */
+/*!
+ \internal
+ \class QFxBlurFilter
+ \ingroup group_effects
+ \brief The QFxBlurFilter class allows you to blur an item.
+*/
+
+QFxBlurFilter::QFxBlurFilter(QObject *parent)
+: QSimpleCanvasFilter(parent), d(new QFxBlurFilterPrivate)
+{
+}
+
+QFxBlurFilter::~QFxBlurFilter()
+{
+ delete d; d = 0;
+}
+
+/*!
+ \qmlproperty real Blur::radius
+
+ Sets the blur kernel radius.
+ The larger the radius the more blurry the item will appear.
+ A radius of 0 (or less) is equivalent to no blur.
+ */
+
+/*!
+ \property QFxBlurFilter::radius
+ \brief the radius of the blur.
+*/
+qreal QFxBlurFilter::radius() const
+{
+ return d->radius;
+}
+
+void QFxBlurFilter::setRadius(qreal radius)
+{
+ if (d->radius == radius) return;
+ d->radius = radius;
+ emit radiusChanged(radius);
+ update();
+}
+
+QRectF QFxBlurFilter::itemBoundingRect(const QRectF &r) const
+{
+ QRectF rv = r;
+ if (d->radius > 0)
+ rv.adjust(-d->radius, -d->radius, d->radius, d->radius);
+ return rv;
+}
+
+#include <math.h>
+void QFxBlurFilter::filterGL(QSimpleCanvasItem::GLPainter &p)
+{
+#if defined(QFX_RENDER_OPENGL2)
+#if 1
+ if (d->radius <= 0) {
+ renderToScreen();
+ return;
+ }
+ float radius = d->radius;
+ QSimpleCanvasItem *item = this->item();
+
+ QRect r = item->itemBoundingRect();
+ float blurScale = 1.0;
+ QRect tr = QRect(QPoint(0, 0), r.size() * blurScale);
+ radius *= blurScale;
+
+ QGLFramebufferObject *fbo = renderToFBO(blurScale);
+ if (!fbo)
+ return;
+
+ float height = r.height();
+ float width = r.width();
+
+ float texWidth = float(tr.width()) / float(fbo->width());
+ float texHeight = float(tr.height()) / float(fbo->height());
+
+ int steps = int(::ceil(radius));
+ int dispSteps = int(::ceil(d->radius));
+ float xstep = texWidth * radius / float(steps * fbo->width());
+ float xinc = steps / float(fbo->width());
+
+ glDisable(GL_BLEND);
+
+ // Render x pass
+ QSize xSize(tr.width() + 2 * steps, tr.height());
+ QGLFramebufferObject *xBlur = acquireFBO(xSize);
+ float xWidth = float(xSize.width()) / float(xBlur->width());
+ float xHeight = float(xSize.height()) / float(xBlur->height());
+ {
+ xBlur->bind();
+
+ GLSaveViewport sv; GLSaveScissor ss;
+ glClearColor(0,0,0,0);
+ glDisable(GL_SCISSOR_TEST);
+ glViewport(0, 0, xBlur->width(), xBlur->height());
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ float vert[] = { 0, xHeight,
+ xWidth, xHeight,
+ 0, 0,
+ xWidth, 0 };
+ float texVert[] = { -xinc, 0,
+ texWidth + xinc, 0,
+ -xinc, texHeight,
+ texWidth + xinc, texHeight };
+
+ QMatrix4x4 trans;
+ trans.translate(-1, -1);
+ trans.scale(2, 2);
+ BlurTextureShader *shader = item->basicShaders()->blurTexture();
+ shader->enable();
+ shader->setTransform(trans);
+ if (steps > 1) {
+ shader->setStep(xstep * 2);
+ shader->setSteps(steps / 2);
+ } else {
+ shader->setStep(xstep);
+ shader->setSteps(steps);
+ }
+ shader->setMode(BlurTextureShader::Horizontal);
+
+ glBindTexture(GL_TEXTURE_2D, fbo->texture());
+
+ shader->setAttributeArray(BlurTextureShader::Vertices, vert, 2);
+ shader->setAttributeArray(BlurTextureShader::TextureCoords, texVert, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(BlurTextureShader::Vertices);
+ shader->disableAttributeArray(BlurTextureShader::TextureCoords);
+ xBlur->release();
+ }
+
+ // Render y pass
+ QSize ySize(xSize.width(), tr.height() + 2 * steps);
+ QGLFramebufferObject *yBlur = acquireFBO(ySize);
+
+ float yWidth = float(ySize.width()) / float(yBlur->width());
+ float yHeight = float(ySize.height()) / float(yBlur->height());
+ float ystep = radius / float(steps * xBlur->height());
+ float yinc = steps / float(xBlur->height());
+ {
+ yBlur->bind();
+
+ GLSaveViewport sv; GLSaveScissor ss;
+ glClearColor(0,0,0,0);
+ glDisable(GL_SCISSOR_TEST);
+ glViewport(0, 0, yBlur->width(), yBlur->height());
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ float vert[] = { 0, yHeight,
+ yWidth, yHeight,
+ 0, 0,
+ yWidth, 0 };
+ float texVert[] = { 0, -yinc,
+ xWidth, -yinc,
+ 0, xHeight + yinc,
+ xWidth, xHeight + yinc };
+
+ QMatrix4x4 trans;
+ trans.translate(-1, -1);
+ trans.scale(2, 2);
+ BlurTextureShader *shader = item->basicShaders()->blurTexture();
+ shader->enable();
+ shader->setTransform(trans);
+ if (steps > 1) {
+ shader->setStep(ystep * 2);
+ shader->setSteps(steps / 2);
+ } else {
+ shader->setStep(ystep);
+ shader->setSteps(steps);
+ }
+ shader->setMode(BlurTextureShader::Vertical);
+
+ glBindTexture(GL_TEXTURE_2D, xBlur->texture());
+
+ shader->setAttributeArray(BlurTextureShader::Vertices, vert, 2);
+ shader->setAttributeArray(BlurTextureShader::TextureCoords, texVert, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(BlurTextureShader::Vertices);
+ shader->disableAttributeArray(BlurTextureShader::TextureCoords);
+ yBlur->release();
+ }
+
+ glEnable(GL_BLEND);
+
+ // Render display pass
+ {
+ glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ float vert[] = { -dispSteps, height + dispSteps,
+ width + dispSteps, height + dispSteps,
+ -dispSteps, -dispSteps,
+ width + dispSteps, -dispSteps };
+ float texVert[] = { 0, 0,
+ yWidth, 0,
+ 0, yHeight,
+ yWidth, yHeight };
+ SingleTextureShader *shader = item->basicShaders()->singleTexture();
+ shader->enable();
+ shader->setTransform(p.activeTransform);
+
+ glBindTexture(GL_TEXTURE_2D, yBlur->texture());
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, texVert, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ releaseFBO(yBlur);
+ releaseFBO(xBlur);
+ releaseFBO(fbo);
+#else
+#if 0
+ if (d->radius <= 0) {
+ renderToScreen();
+ return;
+ }
+ QSimpleCanvasItem *item = this->item();
+
+ QRect r = item->itemBoundingRect();
+
+ float scale = 0.5;
+ float scalePercent = scale / d->radius;
+ QGLFramebufferObject *fbo = renderToFBO(scalePercent);
+ if (!fbo)
+ return;
+
+ QGLFramebufferObject *xfbo = acquireFBO(QSize(scale * r.width(), fbo->height()));
+ QGLFramebufferObject *yfbo = acquireFBO(QSize(scale * r.width(), scale * r.height()));
+
+
+ BlurTextureShader *shader = item->basicShaders()->blurTexture();
+ shader->enable();
+ shader->setTransform(QMatrix4x4());
+
+ // Render up - x
+ {
+ shader->setMode(BlurTextureShader::Horizontal);
+ shader->setStep(1. / float(xfbo->width()));
+
+ GLSaveViewport vp;
+ xfbo->bind();
+ glClearColor(0,0,0,0);
+ glViewport(0, 0, xfbo->width(), xfbo->height());
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ float oWidth = -1. + 2. * float(r.width()) * scale / float(xfbo->width());
+ float oHeight = -1. + 2. * float(r.height()) * scalePercent / float(xfbo->height());
+ float vert[] = {
+ -1, -1,
+ oWidth, -1,
+ -1, oHeight,
+
+ -1, oHeight,
+ oWidth, oHeight,
+ oWidth, -1
+ };
+
+ float tWidth = r.width() * scalePercent / fbo->width();
+ float tHeight = r.height() * scalePercent / fbo->height();
+ float texVert[] = {
+ 0, 0,
+ tWidth, 0,
+ 0, tHeight,
+
+ 0, tHeight,
+ tWidth, tHeight,
+ tWidth, 0
+ };
+
+ glBindTexture(GL_TEXTURE_2D, fbo->texture());
+ shader->setAttributeArray(BlurTextureShader::Vertices, vert, 2);
+ shader->setAttributeArray(BlurTextureShader::TextureCoords, texVert, 2);
+
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ xfbo->release();
+ }
+
+ // Render up - y
+ {
+ shader->setMode(BlurTextureShader::Vertical);
+ shader->setStep(1. / float(yfbo->height()));
+
+ GLSaveViewport vp;
+ yfbo->bind();
+ glClearColor(0,0,0,0);
+ glViewport(0, 0, yfbo->width(), yfbo->height());
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ float oWidth = -1. + 2. * r.width() * scale / yfbo->width();
+ float oHeight = -1. + 2. * r.height() * scale / yfbo->height();
+ float vert[] = {
+ -1, -1,
+ oWidth, -1,
+ -1, oHeight,
+
+ -1, oHeight,
+ oWidth, oHeight,
+ oWidth, -1
+ };
+
+ float tWidth = r.width() * scale / xfbo->width();
+ float tHeight = r.height() * scalePercent / xfbo->height();
+ float texVert[] = {
+ 0, 0,
+ tWidth, 0,
+ 0, tHeight,
+
+ 0, tHeight,
+ tWidth, tHeight,
+ tWidth, 0
+ };
+
+ glBindTexture(GL_TEXTURE_2D, xfbo->texture());
+ shader->setAttributeArray(BlurTextureShader::Vertices, vert, 2);
+ shader->setAttributeArray(BlurTextureShader::TextureCoords, texVert, 2);
+
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ yfbo->release();
+ }
+
+ shader->disableAttributeArray(BlurTextureShader::Vertices);
+ shader->disableAttributeArray(BlurTextureShader::TextureCoords);
+
+ float width = r.width();
+ float height = r.height();
+ //paint to screen
+ {
+ float texWidth = r.width() * scale / float(yfbo->width());
+ float texHeight = r.height() * scale / float(yfbo->height());
+
+ GLfloat vertices[] = { 0, height,
+ width, height,
+ 0, 0,
+ width, 0 };
+ GLfloat texVertices[] = { 0, 0,
+ texWidth, 0,
+ 0, texHeight,
+ texWidth, texHeight };
+
+ glBindTexture(GL_TEXTURE_2D, yfbo->texture());
+
+ SingleTextureOpacityShader *shader =
+ item->basicShaders()->singleTextureOpacity();
+ shader->enable();
+ shader->setTransform(p.activeTransform);
+ shader->setOpacity(p.activeOpacity);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::TextureCoords, texVertices, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::Vertices);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::TextureCoords);
+ }
+
+
+ releaseFBO(fbo);
+ releaseFBO(xfbo);
+ releaseFBO(yfbo);
+#endif
+#endif
+#else
+ Q_UNUSED(p);
+#endif
+
+}
+
+QML_DEFINE_TYPE(QFxBlurFilter,Blur);
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxblurfilter.h b/src/declarative/fx/qfxblurfilter.h
new file mode 100644
index 0000000..7a2b5b9
--- /dev/null
+++ b/src/declarative/fx/qfxblurfilter.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXBLURFILTER_H
+#define QFXBLURFILTER_H
+
+#include <qsimplecanvasfilter.h>
+#include <qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxBlurFilterPrivate;
+class Q_DECLARATIVE_EXPORT QFxBlurFilter : public QSimpleCanvasFilter
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
+public:
+ QFxBlurFilter(QObject *parent=0);
+ virtual ~QFxBlurFilter();
+
+ qreal radius() const;
+ void setRadius(qreal);
+
+Q_SIGNALS:
+ void radiusChanged(qreal);
+
+protected:
+ virtual QRectF itemBoundingRect(const QRectF &) const;
+ virtual void filterGL(QSimpleCanvasItem::GLPainter &p);
+
+private:
+ QFxBlurFilterPrivate *d;
+};
+QML_DECLARE_TYPE(QFxBlurFilter);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXBLURFILTER_H
diff --git a/src/declarative/fx/qfxcomponentinstance.cpp b/src/declarative/fx/qfxcomponentinstance.cpp
new file mode 100644
index 0000000..472b98b
--- /dev/null
+++ b/src/declarative/fx/qfxcomponentinstance.cpp
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxcomponentinstance.h"
+#include "qfxcomponentinstance_p.h"
+#include <qfxperf.h>
+#include <qfxcontentwrapper.h>
+#include <QtDeclarative/qmlinfo.h>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxComponentInstance,ComponentInstance);
+
+/*!
+ \internal
+ \class QFxComponentInstance ComponentInstance
+
+ \brief The QFxComponentInstance class provides a way to instantiate an item from a component.
+ */
+
+/*!
+ \qmlclass ComponentInstance QFxComponentInstance
+ \brief The ComponentInstance item allows you to instantiate a \l{Component}.
+
+ \qml
+ Item {
+ Component {
+ id: RedSquare
+ Rect { color: "red"; width: 10; height: 10 }
+ }
+
+ ComponentInstance { component: RedSquare }
+ }
+ \endqml
+*/
+QFxComponentInstance::QFxComponentInstance(QFxItem *parent)
+ : QFxItem(*(new QFxComponentInstancePrivate), parent)
+{
+ setOptions(IsFocusRealm);
+}
+
+QFxComponentInstance::QFxComponentInstance(QFxComponentInstancePrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ setOptions(IsFocusRealm);
+}
+
+/*!
+ \qmlproperty Component QFxComponentInstance::component
+
+ This property holds the component to instantiate.
+*/
+QmlComponent *QFxComponentInstance::component() const
+{
+ Q_D(const QFxComponentInstance);
+ return d->component;
+}
+
+void QFxComponentInstance::setComponent(QmlComponent *c)
+{
+ Q_D(QFxComponentInstance);
+ if (d->component) {
+ qmlInfo(this) << "component is a write-once property.";
+ return;
+ }
+ d->component = c;
+ create();
+}
+
+void QFxComponentInstance::create()
+{
+ Q_D(QFxComponentInstance);
+ if (d->component) {
+ QObject *obj= d->component->create(qmlContext(this));
+ if (obj) {
+ QFxItem *objitem = qobject_cast<QFxItem *>(obj);
+ if (objitem) {
+ d->instance = objitem;
+ objitem->setItemParent(this);
+ objitem->setFocus(true);
+ connect(objitem, SIGNAL(widthChanged()), this, SLOT(updateSize()));
+ connect(objitem, SIGNAL(heightChanged()), this, SLOT(updateSize()));
+ updateSize();
+ emit instanceChanged();
+ } else {
+ delete obj;
+ }
+ }
+ }
+}
+
+void QFxComponentInstance::updateSize()
+{
+ QFxItem *i = instance();
+ if (i) {
+ if (!widthValid())
+ setImplicitWidth(i->width());
+ if (!heightValid())
+ setImplicitHeight(i->height());
+ }
+}
+
+/*!
+ \qmlproperty Item QFxComponentInstance::instance
+
+ This property holds the instantiated component.
+*/
+QFxItem *QFxComponentInstance::instance() const
+{
+ Q_D(const QFxComponentInstance);
+ return d->instance;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxcomponentinstance.h b/src/declarative/fx/qfxcomponentinstance.h
new file mode 100644
index 0000000..64af355
--- /dev/null
+++ b/src/declarative/fx/qfxcomponentinstance.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXCOMPONENTINSTANCE_H
+#define QFXCOMPONENTINSTANCE_H
+
+#include <qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxComponentInstancePrivate;
+class Q_DECLARATIVE_EXPORT QFxComponentInstance : public QFxItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QmlComponent *component READ component WRITE setComponent)
+ Q_PROPERTY(QFxItem *instance READ instance);
+ Q_CLASSINFO("DefaultProperty", "component")
+public:
+ QFxComponentInstance(QFxItem *parent=0);
+
+ QmlComponent *component() const;
+ void setComponent(QmlComponent *);
+
+ QFxItem *instance() const;
+
+Q_SIGNALS:
+ void instanceChanged();
+
+private slots:
+ void updateSize();
+
+private:
+ void create();
+
+protected:
+ QFxComponentInstance(QFxComponentInstancePrivate &dd, QFxItem *parent);
+
+private:
+ Q_DECLARE_PRIVATE(QFxComponentInstance)
+};
+QML_DECLARE_TYPE(QFxComponentInstance);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXCOMPONENTINSTANCE_H
diff --git a/src/declarative/fx/qfxcomponentinstance_p.h b/src/declarative/fx/qfxcomponentinstance_p.h
new file mode 100644
index 0000000..defeb74
--- /dev/null
+++ b/src/declarative/fx/qfxcomponentinstance_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXCOMPONENTINSTANCE_P_H
+#define QFXCOMPONENTINSTANCE_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 "qfxitem_p.h"
+
+
+QT_BEGIN_NAMESPACE
+class QFxComponentInstancePrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxComponentInstance)
+
+public:
+ QFxComponentInstancePrivate()
+ : component(0), instance(0)
+ {
+ }
+
+ QmlComponent *component;
+ QFxItem *instance;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFXCOMPONENTINSTANCE_P_H
diff --git a/src/declarative/fx/qfxcontentwrapper.cpp b/src/declarative/fx/qfxcontentwrapper.cpp
new file mode 100644
index 0000000..d493990
--- /dev/null
+++ b/src/declarative/fx/qfxcontentwrapper.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxcontentwrapper.h"
+#include "qfxcontentwrapper_p.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxContentWrapper,ContentWrapper);
+
+/*!
+ \qmlclass ContentWrapper QFxContentWrapper
+ \ingroup group_utility
+ \brief ContentWrapper provides a component which contains content.
+ \inherits Item
+
+ In some cases the content of a component is not defined by the component itself.
+ For example, the items placed in a group box need to be specified external to
+ group box component definition itself.
+ In cases like these \l Content can be used to specify at what location in the component
+ the content should be placed. It is used in conjuntion with the \e content property of
+ ContentWrapper: any items listed as content will be placed in the location
+ specified by Content. The component containing the Content must be of type
+ ContentWrapper.
+
+ GroupBox component definition:
+ \quotefile doc/src/snippets/declarative/GroupBox.qml
+
+ \bold Note that in the above component definition ContentWrapper's \e children
+ property is specified explicitly since \e content is the default property.
+
+ Component use:
+ \table
+ \row \o \image content.png
+ \o \quotefile doc/src/snippets/declarative/content.qml
+ \endtable
+
+ \sa Content
+*/
+
+QFxContentWrapper::QFxContentWrapper(QFxItem *parent)
+: QFxItem(*(new QFxContentWrapperPrivate), parent)
+{
+}
+
+QFxContentWrapper::QFxContentWrapper(QFxContentWrapperPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+}
+
+/*!
+ \qmlproperty list<Item> ContentWrapper::content
+
+ Contains the list of elements to replace the \l Content
+ placeholder.
+
+ \sa Content
+*/
+QList<QFxItem *> *QFxContentWrapper::content()
+{
+ Q_D(QFxContentWrapper);
+ return &(d->_content);
+}
+
+void QFxContentWrapper::componentComplete()
+{
+ QFxItem::componentComplete();
+ if (content()->size() < 1)
+ return;
+
+ QList<QSimpleCanvasItem *> nodes;
+ nodes.append(this);
+ QFxItem *target = findContent(nodes);
+ if (!target)
+ return;
+ target = target->itemParent();
+
+ QList<QFxItem*> myContent(*content());
+ for (int ii = 0; ii < myContent.count(); ++ii)
+ myContent.at(ii)->setParent(target);
+}
+
+QFxItem *QFxContentWrapper::findContent(QList<QSimpleCanvasItem *> &nodes)
+{
+ QSimpleCanvasItem *item = nodes.takeFirst();
+ if (qobject_cast<QFxContent*>(item))
+ return static_cast<QFxItem *>(item);
+ nodes << item->children();
+ if (nodes.isEmpty())
+ return 0;
+ return findContent(nodes);
+}
+
+QML_DEFINE_TYPE(QFxContent,Content);
+
+/*!
+ \qmlclass Content QFxContent
+ \ingroup group_utility
+ \brief Content is used as a placeholder for the content of a component.
+ \inherits Item
+
+ The Content element is used to place content within a component.
+ See \l ContentWrapper for usage.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxcontentwrapper.h b/src/declarative/fx/qfxcontentwrapper.h
new file mode 100644
index 0000000..5d5a7e1
--- /dev/null
+++ b/src/declarative/fx/qfxcontentwrapper.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXCONTENTWRAPPER_H
+#define QFXCONTENTWRAPPER_H
+
+#include <qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxContentWrapperPrivate;
+class Q_DECLARATIVE_EXPORT QFxContentWrapper : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QList<QFxItem *>* content READ content DESIGNABLE false)
+ Q_CLASSINFO("DefaultProperty", "content")
+public:
+ QFxContentWrapper(QFxItem *parent=0);
+
+ QList<QFxItem *> *content();
+
+private:
+ void create();
+ QFxItem *findContent(QList<QSimpleCanvasItem *> &nodes);
+
+protected:
+ void componentComplete();
+ QFxContentWrapper(QFxContentWrapperPrivate &dd, QFxItem *parent);
+
+private:
+ Q_DECLARE_PRIVATE(QFxContentWrapper)
+};
+QML_DECLARE_TYPE(QFxContentWrapper);
+
+class Q_DECLARATIVE_EXPORT QFxContent : public QFxItem
+{
+ Q_OBJECT
+public:
+ QFxContent(QFxItem *parent=0) : QFxItem(parent) {}
+};
+QML_DECLARE_TYPE(QFxContent);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXCONTENTWRAPPER_H
diff --git a/src/declarative/fx/qfxcontentwrapper_p.h b/src/declarative/fx/qfxcontentwrapper_p.h
new file mode 100644
index 0000000..4f42e00
--- /dev/null
+++ b/src/declarative/fx/qfxcontentwrapper_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXCONTENTWRAPPER_P_H
+#define QFXCONTENTWRAPPER_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 "qfxitem_p.h"
+#include "qfxcontentwrapper.h"
+
+
+QT_BEGIN_NAMESPACE
+class QFxContentWrapperPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxContentWrapper);
+public:
+ QFxContentWrapperPrivate() { }
+
+ QList<QFxItem *> _content;
+};
+
+QT_END_NAMESPACE
+#endif // QFXCONTENTWRAPPER_P_H
diff --git a/src/declarative/fx/qfxevents.cpp b/src/declarative/fx/qfxevents.cpp
new file mode 100644
index 0000000..195d1e5
--- /dev/null
+++ b/src/declarative/fx/qfxevents.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxevents_p.h"
+
+QT_BEGIN_NAMESPACE
+/*!
+ \qmlclass KeyEvent QFxKeyEvent
+ \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
+ onKeyPress: { if (event.key == Qt.Key_Enter) state = 'ShowDetails'; }
+}
+ \endqml
+
+ The \l KeyActions object could also be used to achieve the above with
+ a clearer syntax.
+
+ \sa KeyActions
+*/
+
+/*!
+ \internal
+ \class QFxKeyEvent
+*/
+
+/*!
+ \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.
+*/
+
+/*!
+ \qmlclass MouseEvent QFxMouseEvent
+ \brief The MouseEvent object provides information about a mouse event.
+
+ The position of the mouse can be found via the x and y properties.
+ The button that caused the event is available via the button property.
+*/
+
+/*!
+ \internal
+ \class QFxMouseEvent
+*/
+
+/*!
+ \qmlproperty int MouseEvent::x
+ \qmlproperty int MouseEvent::y
+
+ These properties hold the position of the mouse event.
+*/
+
+/*!
+ \qmlproperty enum 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.MidButton
+ \endlist
+*/
+
+/*!
+ \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.MidButton
+ \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
+MouseRegion {
+ onClick: { if (mouse.button == Qt.LeftButton && mouse.modifiers & Qt.ShiftModifier) doSomething(); }
+}
+ \endqml
+*/
+
+QML_DEFINE_NOCREATE_TYPE(QFxKeyEvent);
+QML_DEFINE_NOCREATE_TYPE(QFxMouseEvent);
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxevents_p.h b/src/declarative/fx/qfxevents_p.h
new file mode 100644
index 0000000..30717ef
--- /dev/null
+++ b/src/declarative/fx/qfxevents_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXEVENTS_P_H
+#define QFXEVENTS_P_H
+
+#include <qfxglobal.h>
+#include <qml.h>
+#include <QtCore/qobject.h>
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFxKeyEvent : 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:
+ QFxKeyEvent(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); }
+ QFxKeyEvent(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;
+};
+
+QML_DECLARE_TYPE(QFxKeyEvent);
+
+class QFxMouseEvent : 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:
+ QFxMouseEvent(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(false) {}
+
+ 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; }
+
+ 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;
+};
+
+QML_DECLARE_TYPE(QFxMouseEvent);
+
+QT_END_NAMESPACE
+
+#endif // QFXEVENTS_P_H
diff --git a/src/declarative/fx/qfxflickable.cpp b/src/declarative/fx/qfxflickable.cpp
new file mode 100644
index 0000000..4248ebb
--- /dev/null
+++ b/src/declarative/fx/qfxflickable.cpp
@@ -0,0 +1,1153 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxflickable.h"
+#include "qfxflickable_p.h"
+
+#include <QGraphicsSceneMouseEvent>
+#include <QPointer>
+#include <QTimer>
+
+QT_BEGIN_NAMESPACE
+
+ElasticValue::ElasticValue(QmlTimeLineValue &val)
+ : _value(val)
+{
+ _to = _value.value();
+ _myValue = _to;
+ _velocity = 0;
+}
+
+void ElasticValue::setValue(qreal to)
+{
+ if (_to != to) {
+ _to = to;
+ _startTime.start();
+ if (state() != Running)
+ start();
+ }
+}
+
+void ElasticValue::clear()
+{
+ stop();
+ _velocity = 0.0;
+ _myValue = _value.value();
+}
+
+void ElasticValue::updateCurrentTime(int)
+{
+ const qreal Tension = 0.1;
+ int elapsed = _startTime.restart();
+ if (!elapsed)
+ return;
+ qreal dist = _to - _value.value();
+ qreal move = Tension * dist * qAbs(dist);
+ if (elapsed < 100 && _velocity != 0.0)
+ move = (elapsed * move + (100 - elapsed) * _velocity) / 100;
+ _myValue += move * elapsed / 1000;
+ _value.setValue(qRound(_myValue)); // moving sub-pixel can be ugly.
+// _value.setValue(_myValue);
+ _velocity = move;
+ if (qAbs(_velocity) < 5.0)
+ clear();
+ emit updated();
+}
+
+QFxFlickablePrivate::QFxFlickablePrivate()
+ : _flick(new QFxItem), _moveX(_flick, &QFxItem::setX), _moveY(_flick, &QFxItem::setY)
+ , vWidth(-1), vHeight(-1), overShoot(true), flicked(false), moving(false), stealMouse(false)
+ , pressed(false), maxVelocity(-1), locked(false), dragMode(QFxFlickable::Hard)
+ , elasticY(_moveY), elasticX(_moveX), velocityDecay(100), xVelocity(this), yVelocity(this)
+ , vTime(0), atXEnd(false), atXBeginning(true), pageXPosition(0.), pageWidth(0.)
+ , atYEnd(false), atYBeginning(true), pageYPosition(0.), pageHeight(0.)
+{
+ fixupXEvent = QmlTimeLineEvent::timeLineEvent<QFxFlickablePrivate, &QFxFlickablePrivate::fixupX>(&_moveX, this);
+ fixupYEvent = QmlTimeLineEvent::timeLineEvent<QFxFlickablePrivate, &QFxFlickablePrivate::fixupY>(&_moveY, this);
+}
+
+void QFxFlickablePrivate::init()
+{
+ Q_Q(QFxFlickable);
+ _flick->setParent(q);
+ QObject::connect(&_tl, SIGNAL(updated()), q, SLOT(ticked()));
+ QObject::connect(&_tl, SIGNAL(completed()), q, SLOT(movementEnding()));
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setOptions(QSimpleCanvasItem::ChildMouseFilter | QSimpleCanvasItem::MouseEvents);
+ QObject::connect(_flick, SIGNAL(leftChanged()), q, SIGNAL(positionChanged()));
+ QObject::connect(_flick, SIGNAL(topChanged()), q, SIGNAL(positionChanged()));
+ QObject::connect(&elasticX, SIGNAL(updated()), q, SLOT(ticked()));
+ QObject::connect(&elasticY, SIGNAL(updated()), q, SLOT(ticked()));
+ QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(heightChange()));
+ QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(widthChange()));
+}
+
+void QFxFlickablePrivate::fixupX()
+{
+ Q_Q(QFxFlickable);
+ if (!q->xflick() || _moveX.timeLine())
+ return;
+
+ vTime = _tl.time();
+
+ if (_moveX.value() > q->minXExtent() || q->maxXExtent() > 0) {
+ _tl.clear();
+ _tl.move(_moveX, q->minXExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ flicked = false;
+ //emit flickingChanged();
+ } else if (_moveX.value() < q->maxXExtent()) {
+ _tl.clear();
+ _tl.move(_moveX, q->maxXExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ flicked = false;
+ //emit flickingChanged();
+ }
+}
+
+void QFxFlickablePrivate::fixupY()
+{
+ Q_Q(QFxFlickable);
+ if (!q->yflick() || _moveY.timeLine())
+ return;
+
+ vTime = _tl.time();
+
+ if (_moveY.value() > q->minYExtent() || (q->maxYExtent() > q->minYExtent())) {
+ _tl.clear();
+ _tl.move(_moveY, q->minYExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ //emit flickingChanged();
+ } else if (_moveY.value() < q->maxYExtent()) {
+ _tl.clear();
+ _tl.move(_moveY, q->maxYExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ //emit flickingChanged();
+ } else {
+ flicked = false;
+ }
+}
+
+void QFxFlickablePrivate::updateBeginningEnd()
+{
+ Q_Q(QFxFlickable);
+ bool pageChange = false;
+ bool atBoundaryChange = false;
+
+ // Vertical
+ const int viewheight = q->height();
+ const int maxyextent = int(-q->maxYExtent());
+ const qreal ypos = -_moveY.value();
+ qreal pagePos = ((ypos * 100.0) / (maxyextent + viewheight)) / 100.0;
+ qreal pageSize = ((viewheight * 100.0) / (maxyextent + viewheight)) / 100.0;
+ bool atBeginning = (ypos <= 0.0);
+ bool atEnd = (maxyextent <= ypos);
+
+ if (pageSize != pageHeight) {
+ pageHeight = pageSize;
+ pageChange = true;
+ }
+ if (pagePos != pageYPosition) {
+ pageYPosition = pagePos;
+ pageChange = true;
+ }
+ if (atBeginning != atYBeginning) {
+ atYBeginning = atBeginning;
+ atBoundaryChange = true;
+ }
+ if (atEnd != atYEnd) {
+ atYEnd = atEnd;
+ atBoundaryChange = true;
+ }
+
+ // Horizontal
+ const int viewwidth = q->width();
+ const int maxxextent = int(-q->maxXExtent());
+ const qreal xpos = -_moveX.value();
+ pagePos = ((xpos * 100.0) / (maxxextent + viewwidth)) / 100.0;
+ pageSize = ((viewwidth * 100.0) / (maxxextent + viewwidth)) / 100.0;
+ atBeginning = (xpos <= 0.0);
+ atEnd = (maxxextent <= xpos);
+
+ if (pageSize != pageWidth) {
+ pageWidth = pageSize;
+ pageChange = true;
+ }
+ if (pagePos != pageXPosition) {
+ pageXPosition = pagePos;
+ pageChange = true;
+ }
+ if (atBeginning != atXBeginning) {
+ atXBeginning = atBeginning;
+ atBoundaryChange = true;
+ }
+ if (atEnd != atXEnd) {
+ atXEnd = atEnd;
+ atBoundaryChange = true;
+ }
+
+ if (pageChange)
+ emit q->pageChanged();
+ if (atBoundaryChange)
+ emit q->isAtBoundaryChanged();
+}
+
+static const int FlickThreshold = 5;
+
+QML_DEFINE_TYPE(QFxFlickable,Flickable);
+
+/*!
+ \qmlclass Flickable
+ \brief The Flickable item provides a surface that can be "flicked".
+ \inherits Item
+
+ Flickable places its children on a surface that can be dragged and flicked.
+
+ \code
+ Flickable {
+ width: 200; height: 200; viewportWidth: image.width; viewportHeight: image.height
+ Image { id: image; source: "bigimage.png" }
+ }
+ \endcode
+
+ \image flickable.gif
+
+ \note Flickable does not automatically clip its contents. If
+ it is not full-screen it is likely that \c clip should be set
+ to true.
+
+ \note Due to an implementation detail items placed inside a flickable cannot anchor to it by
+ id, use 'parent' instead.
+*/
+
+/*!
+ \internal
+ \class QFxFlickable
+ \brief The QFxFlickable class provides a view that can be "flicked".
+
+ \ingroup group_widgets
+
+ QFxFlickable allows its children to be dragged and flicked.
+
+\code
+Flickable {
+ width: 320; height: 480; viewportWidth: image.width; viewportHeight: image.height
+ Image { id: image; source: "bigimage.png" }
+}
+\endcode
+
+ Note that QFxFlickable does not automatically clip its contents. If
+ it is not full-screen it is likely that QFxItem::clip should be set
+ to true.
+
+*/
+
+QFxFlickable::QFxFlickable(QFxItem *parent)
+ : QFxItem(*(new QFxFlickablePrivate), parent)
+{
+ Q_D(QFxFlickable);
+ d->init();
+}
+
+QFxFlickable::QFxFlickable(QFxFlickablePrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxFlickable);
+ d->init();
+}
+
+QFxFlickable::~QFxFlickable()
+{
+}
+
+/*!
+ \qmlproperty int Flickable::xPosition
+ \qmlproperty int Flickable::yPosition
+
+ 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 yPosition will be 100.
+*/
+
+/*!
+ \property QFxFlickable::xPosition
+ \brief the x position of the view.
+
+ The xPosition represents the left-most visible coordinate in the view.
+*/
+qreal QFxFlickable::xPosition() const
+{
+ Q_D(const QFxFlickable);
+ return -d->_moveX.value();
+}
+
+void QFxFlickable::setXPosition(qreal pos)
+{
+ Q_D(QFxFlickable);
+ pos = qRound(pos);
+ if (-pos != d->_moveX.value()) {
+ d->_tl.reset(d->_moveX);
+ d->_moveX.setValue(-pos);
+ viewportMoved();
+ }
+}
+
+/*!
+ \property QFxFlickable::yPosition
+ \brief the y position of the view.
+
+ The yPosition represents the top-most visible coordinate in the view.
+*/
+qreal QFxFlickable::yPosition() const
+{
+ Q_D(const QFxFlickable);
+ return -d->_moveY.value();
+}
+
+void QFxFlickable::setYPosition(qreal pos)
+{
+ Q_D(QFxFlickable);
+ pos = qRound(pos);
+ if (-pos != d->_moveY.value()) {
+ d->_tl.reset(d->_moveY);
+ d->_moveY.setValue(-pos);
+ viewportMoved();
+ }
+}
+
+/*!
+ \qmlproperty bool Flickable::locked
+
+ A user cannot drag or flick a Flickable that is locked.
+
+ 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 viewing detailed information on a location popup that is a child of the Flickable.
+*/
+
+/*!
+ \property QFxFlickable::locked
+ \brief determines whether the user can move the view.
+
+ If the Flickable is locked, the user cannot move the view.
+*/
+bool QFxFlickable::isLocked() const
+{
+ Q_D(const QFxFlickable);
+ return d->locked;
+}
+
+void QFxFlickable::setLocked(bool lock)
+{
+ Q_D(QFxFlickable);
+ d->locked = lock;
+}
+
+/*!
+ \qmlproperty enumeration Flickable::dragMode
+ This property contains the kind of 'physics' applied when dragging the surface.
+
+ Two modes are supported:
+ \list
+ \i Hard - the view follows the user's input exactly.
+ \i Elastic - the view moves elastically in response to the user's input.
+ \endlist
+*/
+
+/*!
+ \property QFxFlickable::dragMode
+ \brief sets the kind of 'physics' applied when dragging the view.
+
+ Two modes are supported:
+ \list
+ \i Hard - the view follows the user's input exactly.
+ \i Elastic - the view moves elastically in response to the user's input.
+ \endlist
+*/
+QFxFlickable::DragMode QFxFlickable::dragMode() const
+{
+ Q_D(const QFxFlickable);
+ return d->dragMode;
+}
+
+void QFxFlickable::setDragMode(DragMode mode)
+{
+ Q_D(QFxFlickable);
+ d->dragMode = mode;
+}
+
+/*!
+ \qmlproperty real Flickable::xVelocity
+ \qmlproperty real Flickable::yVelocity
+
+ The instantaneous velocity of movement along the x and y axes, in pixels/sec.
+*/
+
+/*!
+ \property QFxFlickable::xVelocity
+ \brief provides the instantaneous velocity of movement in the x-axis (pixels/sec).
+*/
+qreal QFxFlickable::xVelocity() const
+{
+ Q_D(const QFxFlickable);
+ return d->xVelocity.value();
+}
+
+/*!
+ \property QFxFlickable::yVelocity
+ \brief provides the instantaneous velocity of movement in the y-axis (pixels/sec).
+*/
+qreal QFxFlickable::yVelocity() const
+{
+ Q_D(const QFxFlickable);
+ return d->yVelocity.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 QFxFlickable::isAtXEnd() const
+{
+ Q_D(const QFxFlickable);
+ return d->atXEnd;
+}
+
+bool QFxFlickable::isAtXBeginning() const
+{
+ Q_D(const QFxFlickable);
+ return d->atXBeginning;
+}
+
+bool QFxFlickable::isAtYEnd() const
+{
+ Q_D(const QFxFlickable);
+ return d->atYEnd;
+}
+
+bool QFxFlickable::isAtYBeginning() const
+{
+ Q_D(const QFxFlickable);
+ return d->atYBeginning;
+}
+
+/*!
+ \qmlproperty real Flickable::pageXPosition
+ \qmlproperty real Flickable::pageWidth
+ \qmlproperty real Flickable::pageYPosition
+ \qmlproperty real Flickable::pageHeight
+
+ These properties describe the position and size of the currently viewed page.
+ The page size is defined as the percentage of the full view currently visible,
+ scaled to 0.0 - 1.0. The page position is also in the range 0.0 (beginning) to
+ 1.0 (end).
+
+ These properties are typically used to draw a scrollbar, for example:
+ \code
+ Rect {
+ opacity: 0.5; anchors.right: MyListView.right-2; width: 6
+ y: MyListView.pageYPosition * MyListView.height
+ height: MyListView.pageHeight * MyListView.height
+ }
+ \endcode
+*/
+qreal QFxFlickable::pageWidth() const
+{
+ Q_D(const QFxFlickable);
+ return d->pageWidth;
+}
+
+qreal QFxFlickable::pageXPosition() const
+{
+ Q_D(const QFxFlickable);
+ return d->pageXPosition;
+}
+
+qreal QFxFlickable::pageHeight() const
+{
+ Q_D(const QFxFlickable);
+ return d->pageHeight;
+}
+
+qreal QFxFlickable::pageYPosition() const
+{
+ Q_D(const QFxFlickable);
+ return d->pageYPosition;
+}
+
+void QFxFlickable::ticked()
+{
+ viewportMoved();
+}
+
+QFxItem *QFxFlickable::viewport()
+{
+ Q_D(QFxFlickable);
+ return d->_flick;
+}
+
+qreal QFxFlickable::visibleX() const
+{
+ Q_D(const QFxFlickable);
+ return -d->_moveX.value();
+}
+
+qreal QFxFlickable::visibleY() const
+{
+ Q_D(const QFxFlickable);
+ return -d->_moveY.value();
+}
+
+void QFxFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (!locked && _tl.isActive() && (qAbs(velocityX) > 10 || qAbs(velocityY) > 10))
+ stealMouse = true; // If we've been flicked then steal the click.
+ else
+ stealMouse = false;
+ pressed = true;
+ _tl.clear();
+ velocityX = -1;
+ velocityY = -1;
+ lastPos = QPoint();
+ lastPosTime.start();
+ pressPos = event->pos();
+ pressX = _moveX.value();
+ pressY = _moveY.value();
+ flicked = false;
+ pressTime.start();
+ if (dragMode == QFxFlickable::Elastic) {
+ elasticX.clear();
+ elasticY.clear();
+ }
+ velocityTime.start();
+}
+
+void QFxFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QFxFlickable);
+ if (locked || lastPosTime.isNull())
+ return;
+ bool rejectY = false;
+ bool rejectX = false;
+ bool moved = false;
+
+ if (q->yflick()) {
+ int dy = int(event->pos().y() - pressPos.y());
+ if (qAbs(dy) > FlickThreshold || pressTime.elapsed() > 200) {
+ qreal newY = dy + pressY;
+ const qreal minY = q->minYExtent();
+ const qreal maxY = q->maxYExtent();
+ if (newY > minY)
+ newY = minY + (newY - minY) / 2;
+ if (newY < maxY && maxY - minY < 0)
+ newY = maxY + (newY - maxY) / 2;
+ if (q->overShoot() || (newY <= minY && newY >= maxY)) {
+ if (dragMode == QFxFlickable::Hard)
+ _moveY.setValue(newY);
+ else
+ elasticY.setValue(newY);
+ moved = true;
+ } else if (!q->overShoot())
+ rejectY = true;
+ if (qAbs(dy) > FlickThreshold)
+ stealMouse = true;
+ }
+ }
+
+ if (q->xflick()) {
+ int dx = int(event->pos().x() - pressPos.x());
+ if (qAbs(dx) > FlickThreshold || pressTime.elapsed() > 200) {
+ qreal newX = dx + pressX;
+ if (q->overShoot() || (newX <= q->minXExtent() && newX >= q->maxXExtent())) {
+ if (dragMode == QFxFlickable::Hard)
+ _moveX.setValue(newX);
+ else
+ elasticX.setValue(newX);
+ moved = true;
+ } else if (!q->overShoot())
+ rejectX = true;
+ if (qAbs(dx) > FlickThreshold)
+ stealMouse = true;
+ }
+ }
+
+ if (!lastPos.isNull()) {
+ qreal elapsed = qreal(lastPosTime.restart()) / 1000.;
+ if (elapsed <= 0)
+ elapsed = 1;
+ if (q->yflick()) {
+ qreal diff = event->pos().y() - lastPos.y();
+ velocityY = diff / elapsed;
+ }
+
+ if (q->xflick()) {
+ qreal diff = event->pos().x() - lastPos.x();
+ velocityX = diff / elapsed;
+ }
+ }
+
+ if (rejectY) velocityY = 0;
+ if (rejectX) velocityX = 0;
+
+ if (moved) {
+ q->viewportMoved();
+ q->movementStarting();
+ }
+
+ lastPos = event->pos();
+}
+
+void QFxFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *)
+{
+ Q_Q(QFxFlickable);
+
+ pressed = false;
+ if (lastPosTime.isNull())
+ return;
+
+ if (dragMode == QFxFlickable::Elastic) {
+ elasticY.clear();
+ elasticX.clear();
+ }
+
+ vTime = _tl.time();
+ if (qAbs(velocityY) > 10) {
+ qreal maxDistance = -1;
+ // -ve velocity means list is moving up
+ if (velocityY > 0) {
+ if (_moveY.value() < q->minYExtent())
+ maxDistance = qAbs(q->minYExtent() -_moveY.value() + (overShoot?30:0));
+ } else {
+ if (_moveY.value() > q->maxYExtent())
+ maxDistance = qAbs(q->maxYExtent() - _moveY.value()) + (overShoot?30:0);
+ }
+ if (maxDistance > 0) {
+ qreal v = velocityY;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ _tl.accel(_moveY, v, 500, maxDistance);
+ _tl.execute(fixupYEvent);
+ flicked = true;
+ emit q->flickingChanged();
+ emit q->flickStarted();
+ } else {
+ fixupY();
+ }
+ } else {
+ fixupY();
+ }
+ if (qAbs(velocityX) > 10) {
+ qreal maxDistance = -1;
+ // -ve velocity means list is moving up
+ if (velocityX > 0) {
+ if (_moveX.value() < q->minXExtent())
+ maxDistance = qAbs(q->minXExtent()) -_moveX.value() + (overShoot?30:0);
+ } else {
+ if (_moveX.value() > q->maxXExtent())
+ maxDistance = qAbs(q->maxXExtent() - _moveX.value()) + (overShoot?30:0);
+ }
+ if (maxDistance > 0) {
+ qreal v = velocityX;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ _tl.accel(_moveX, v, 500, maxDistance);
+ _tl.execute(fixupXEvent);
+ flicked = true;
+ emit q->flickingChanged();
+ emit q->flickStarted();
+ } else {
+ fixupX();
+ }
+ } else {
+ fixupX();
+ }
+ stealMouse = false;
+ lastPosTime = QTime();
+
+ if (!_tl.isActive())
+ q->movementEnding();
+}
+
+void QFxFlickable::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxFlickable);
+ d->handleMousePressEvent(event);
+ event->accept();
+}
+
+void QFxFlickable::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxFlickable);
+ d->handleMouseMoveEvent(event);
+ event->accept();
+}
+
+void QFxFlickable::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxFlickable);
+ d->handleMouseReleaseEvent(event);
+ event->accept();
+}
+
+qreal QFxFlickable::minYExtent() const
+{
+ return 0.0;
+}
+
+qreal QFxFlickable::minXExtent() const
+{
+ return 0.0;
+}
+
+/* returns -ve */
+qreal QFxFlickable::maxXExtent() const
+{
+ return width() - vWidth();
+}
+/* returns -ve */
+qreal QFxFlickable::maxYExtent() const
+{
+ return height() - vHeight();
+}
+
+void QFxFlickable::viewportMoved()
+{
+ Q_D(QFxFlickable);
+ //XXX should look at moveX here as well
+ if (d->flicked && (d->_moveY.value() > minYExtent() + (d->overShoot?30:0)
+ || d->_moveY.value() < maxYExtent() - (d->overShoot?30:0))){
+ d->flicked = false;
+ emit flickingChanged();
+ emit flickEnded();
+ d->_tl.reset(d->_moveY);
+ d->fixupY();
+ }
+
+ int elapsed = d->velocityTime.elapsed();
+
+ if (elapsed) {
+ qreal prevY = d->lastFlickablePosition.x();
+ qreal prevX = d->lastFlickablePosition.y();
+ d->velocityTimeline.clear();
+ if (d->pressed) {
+ qreal xVelocity = (prevX - d->_moveX.value()) * 1000 / elapsed;
+ qreal yVelocity = (prevY - d->_moveY.value()) * 1000 / elapsed;
+ d->velocityTimeline.move(d->xVelocity, xVelocity, d->velocityDecay);
+ d->velocityTimeline.move(d->xVelocity, 0, d->velocityDecay);
+ d->velocityTimeline.move(d->yVelocity, yVelocity, d->velocityDecay);
+ d->velocityTimeline.move(d->yVelocity, 0, d->velocityDecay);
+ } else {
+ if (d->_tl.time() != d->vTime) {
+ qreal xVelocity = (prevX - d->_moveX.value()) * 1000 / (d->_tl.time() - d->vTime);
+ qreal yVelocity = (prevY - d->_moveY.value()) * 1000 / (d->_tl.time() - d->vTime);
+ d->xVelocity.setValue(xVelocity);
+ d->yVelocity.setValue(yVelocity);
+ }
+ d->vTime = d->_tl.time();
+ }
+ }
+
+ d->lastFlickablePosition = QPointF(d->_moveY.value(), d->_moveX.value());
+ d->velocityTime.restart();
+ d->updateBeginningEnd();
+}
+
+void QFxFlickablePrivate::data_removeAt(int)
+{
+ // ###
+}
+
+int QFxFlickablePrivate::data_count() const
+{
+ // ###
+ return 0;
+}
+
+void QFxFlickablePrivate::data_append(QObject *o)
+{
+ Q_Q(QFxFlickable);
+ QFxItem *i = qobject_cast<QFxItem *>(o);
+ if (i)
+ _flick->children()->append(i);
+ else
+ o->setParent(q);
+}
+
+void QFxFlickablePrivate::data_insert(int, QObject *)
+{
+ // ###
+}
+
+QObject *QFxFlickablePrivate::data_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QFxFlickablePrivate::data_clear()
+{
+ // ###
+}
+
+
+QmlList<QObject *> *QFxFlickable::flickableData()
+{
+ Q_D(QFxFlickable);
+ return &d->data;
+}
+
+QmlList<QFxItem *> *QFxFlickable::flickableChildren()
+{
+ Q_D(QFxFlickable);
+ return d->_flick->children();
+}
+
+/*!
+ \qmlproperty bool Flickable::overShoot
+ This property holds the number of pixels the surface may overshoot the
+ Flickable's boundaries when flicked.
+
+ If overShoot is non-zero the contents can be flicked beyond the boundary
+ of the Flickable before being moved back to the boundary. This provides
+ the feeling that the edges of the view are soft, rather than a hard
+ physical boundary.
+*/
+
+/*!
+ \property QFxFlickable::overShoot
+ \brief the number of pixels the view may overshoot the boundaries when flicked.
+
+ If overShoot is non-zero the contents can be flicked beyond the boundary
+ of the view before being moved back to the boundary. This provides
+ the feeling that the edges of the view are soft, rather than a hard
+ physical boundary.
+*/
+bool QFxFlickable::overShoot() const
+{
+ Q_D(const QFxFlickable);
+ return d->overShoot;
+}
+
+void QFxFlickable::setOverShoot(bool o)
+{
+ Q_D(QFxFlickable);
+ d->overShoot = o;
+}
+
+/*!
+ \qmlproperty int Flickable::viewportWidth
+ \qmlproperty int Flickable::viewportHeight
+
+ The dimensions of the viewport (the surface controlled by Flickable). Typically this
+ should be set to the combined size of the items placed in the Flickable.
+
+ \code
+ Flickable {
+ width: 320; height: 480; viewportWidth: image.width; viewportHeight: image.height
+ Image { id: image; source: "bigimage.png" }
+ }
+ \endcode
+*/
+
+/*!
+ \property QFxFlickable::viewportWidth
+ \brief the width of the view.
+*/
+int QFxFlickable::viewportWidth() const
+{
+ Q_D(const QFxFlickable);
+ return d->vWidth;
+}
+
+void QFxFlickable::setViewportWidth(int w)
+{
+ Q_D(QFxFlickable);
+ if (d->vWidth == w)
+ return;
+ d->vWidth = w;
+ if (w < 0)
+ d->_flick->setWidth(width());
+ else
+ d->_flick->setWidth(w);
+ // Make sure that we're entirely in view.
+ if (d->_moveX.value() > minXExtent() || maxXExtent() > 0) {
+ d->_tl.clear();
+ d->_moveX.setValue(minXExtent());
+ } else if (d->_moveX.value() < maxXExtent()) {
+ d->_tl.clear();
+ d->_moveX.setValue(maxXExtent());
+ }
+ emit viewportWidthChanged();
+ d->updateBeginningEnd();
+}
+
+void QFxFlickable::widthChange()
+{
+ Q_D(QFxFlickable);
+ if (d->vWidth < 0) {
+ d->_flick->setWidth(width());
+ emit viewportWidthChanged();
+ d->updateBeginningEnd();
+ }
+}
+
+void QFxFlickable::heightChange()
+{
+ Q_D(QFxFlickable);
+ if (d->vHeight < 0) {
+ d->_flick->setHeight(height());
+ emit viewportHeightChanged();
+ d->updateBeginningEnd();
+ }
+}
+
+/*!
+ \property QFxFlickable::viewportHeight
+ \brief the height of the view.
+*/
+int QFxFlickable::viewportHeight() const
+{
+ Q_D(const QFxFlickable);
+ return d->vHeight;
+}
+
+void QFxFlickable::setViewportHeight(int h)
+{
+ Q_D(QFxFlickable);
+ if (d->vHeight == h)
+ return;
+ d->vHeight = h;
+ if (h < 0)
+ d->_flick->setHeight(height());
+ else
+ d->_flick->setHeight(h);
+ // Make sure that we're entirely in view.
+ if (d->_moveY.value() > minYExtent() || maxYExtent() > 0) {
+ d->_tl.clear();
+ d->_moveY.setValue(minYExtent());
+ } else if (d->_moveY.value() < maxYExtent()) {
+ d->_tl.clear();
+ d->_moveY.setValue(maxYExtent());
+ }
+ emit viewportHeightChanged();
+ d->updateBeginningEnd();
+}
+
+int QFxFlickable::vWidth() const
+{
+ Q_D(const QFxFlickable);
+ if (d->vWidth < 0)
+ return width();
+ else
+ return d->vWidth;
+}
+
+int QFxFlickable::vHeight() const
+{
+ Q_D(const QFxFlickable);
+ if (d->vHeight < 0)
+ return height();
+ else
+ return d->vHeight;
+}
+
+bool QFxFlickable::xflick() const
+{
+ return vWidth() != width();
+}
+
+bool QFxFlickable::yflick() const
+{
+ return vHeight() != height();
+}
+
+bool QFxFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxFlickable);
+ QGraphicsSceneMouseEvent mouseEvent(event->type());
+ QRectF myRect = mapToScene(QRectF(0, 0, width(), height()));
+ QFxItem *grabber = static_cast<QFxItem*>(mouseGrabberItem());
+ if ((d->stealMouse || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) {
+ 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:
+ d->handleMousePressEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ d->handleMouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = static_cast<QFxItem*>(mouseGrabberItem());
+ if (grabber && d->stealMouse && !grabber->keepMouseGrab())
+ grabMouse();
+
+ return d->stealMouse;
+ } else if (!d->lastPosTime.isNull()) {
+ d->lastPosTime = QTime();
+ }
+ return false;
+}
+
+bool QFxFlickable::mouseFilter(QGraphicsSceneMouseEvent *e)
+{
+ if (!isVisible())
+ return false;
+ switch (e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ return sendMouseEvent(e);
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/*!
+ \qmlproperty int Flickable::maximumFlickVelocity
+ This property holds the maximum velocity that the user can flick the view.
+*/
+
+/*!
+ \property QFxFlickable::maximumFlickVelocity
+ \brief the maximum velocity that the user can flick the view.
+*/
+int QFxFlickable::maximumFlickVelocity() const
+{
+ Q_D(const QFxFlickable);
+ return d->maxVelocity;
+}
+
+void QFxFlickable::setMaximumFlickVelocity(int v)
+{
+ Q_D(QFxFlickable);
+ if (v == d->maxVelocity)
+ return;
+ d->maxVelocity = v;
+}
+
+bool QFxFlickable::isFlicking() const
+{
+ Q_D(const QFxFlickable);
+ return d->flicked;
+}
+
+int QFxFlickable::velocityDecay() const
+{
+ Q_D(const QFxFlickable);
+ return d->velocityDecay;
+}
+
+void QFxFlickable::setVelocityDecay(int decay)
+{
+ Q_D(QFxFlickable);
+ Q_ASSERT(decay >= 0);
+ if (decay == d->velocityDecay)
+ return;
+ d->velocityDecay = decay;
+ emit velocityDecayChanged(decay);
+}
+
+bool QFxFlickable::isMoving() const
+{
+ Q_D(const QFxFlickable);
+ return d->moving;
+}
+
+void QFxFlickable::movementStarting()
+{
+ Q_D(QFxFlickable);
+ if (!d->moving) {
+ d->moving = true;
+ emit movingChanged();
+ emit movementStarted();
+ }
+}
+
+void QFxFlickable::movementEnding()
+{
+ Q_D(QFxFlickable);
+ if (d->moving) {
+ d->moving = false;
+ emit movingChanged();
+ emit movementEnded();
+ }
+ if (d->flicked) {
+ d->flicked = false;
+ emit flickingChanged();
+ emit flickEnded();
+ }
+ d->xVelocity.setValue(0);
+}
+
+void QFxFlickablePrivate::updateVelocity()
+{
+ Q_Q(QFxFlickable);
+ emit q->velocityChanged(q->xVelocity(), q->yVelocity());
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxflickable.h b/src/declarative/fx/qfxflickable.h
new file mode 100644
index 0000000..c5a0593
--- /dev/null
+++ b/src/declarative/fx/qfxflickable.h
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXFLICKABLE_H
+#define QFXFLICKABLE_H
+
+#include <qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxFlickablePrivate;
+class Q_DECLARATIVE_EXPORT QFxFlickable : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool overShoot READ overShoot WRITE setOverShoot)
+ Q_PROPERTY(int viewportWidth READ viewportWidth WRITE setViewportWidth NOTIFY viewportWidthChanged)
+ Q_PROPERTY(int viewportHeight READ viewportHeight WRITE setViewportHeight NOTIFY viewportHeightChanged)
+ Q_PROPERTY(qreal xPosition READ xPosition WRITE setXPosition NOTIFY positionChanged);
+ Q_PROPERTY(qreal yPosition READ yPosition WRITE setYPosition NOTIFY positionChanged);
+ Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged)
+ Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
+ Q_PROPERTY(int velocityDecay READ velocityDecay WRITE setVelocityDecay NOTIFY velocityDecayChanged)
+ Q_PROPERTY(int maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity)
+ Q_PROPERTY(bool locked READ isLocked WRITE setLocked)
+ Q_PROPERTY(DragMode dragMode READ dragMode WRITE setDragMode)
+ Q_PROPERTY(qreal xVelocity READ xVelocity NOTIFY velocityChanged)
+ Q_PROPERTY(qreal yVelocity READ yVelocity NOTIFY velocityChanged)
+ 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(qreal pageXPosition READ pageXPosition NOTIFY pageChanged);
+ Q_PROPERTY(qreal pageYPosition READ pageYPosition NOTIFY pageChanged);
+ Q_PROPERTY(qreal pageWidth READ pageWidth NOTIFY pageChanged);
+ Q_PROPERTY(qreal pageHeight READ pageHeight NOTIFY pageChanged);
+
+ Q_PROPERTY(QmlList<QObject *>* flickableData READ flickableData);
+ Q_PROPERTY(QmlList<QFxItem *>* flickableChildren READ flickableChildren);
+ Q_CLASSINFO("DefaultProperty", "flickableData")
+
+public:
+ QFxFlickable(QFxItem *parent=0);
+ ~QFxFlickable();
+
+ QmlList<QObject *> *flickableData();
+ QmlList<QFxItem *> *flickableChildren();
+
+ bool overShoot() const;
+ void setOverShoot(bool);
+
+ int viewportWidth() const;
+ void setViewportWidth(int);
+
+ int viewportHeight() const;
+ void setViewportHeight(int);
+
+ qreal xPosition() const;
+ void setXPosition(qreal pos);
+
+ qreal yPosition() const;
+ void setYPosition(qreal pos);
+
+ bool isMoving() const;
+ bool isFlicking() const;
+
+ int velocityDecay() const;
+ void setVelocityDecay(int);
+
+ int maximumFlickVelocity() const;
+ void setMaximumFlickVelocity(int);
+
+ bool isLocked() const;
+ void setLocked(bool);
+
+ Q_ENUMS(DragMode);
+ enum DragMode { Hard, Elastic };
+ DragMode dragMode() const;
+ void setDragMode(DragMode mode);
+
+ qreal xVelocity() const;
+ qreal yVelocity() const;
+
+ bool isAtXEnd() const;
+ bool isAtXBeginning() const;
+ qreal pageXPosition() const;
+ qreal pageWidth() const;
+
+ bool isAtYEnd() const;
+ bool isAtYBeginning() const;
+ qreal pageYPosition() const;
+ qreal pageHeight() const;
+
+ QFxItem *viewport();
+
+Q_SIGNALS:
+ void viewportWidthChanged();
+ void viewportHeightChanged();
+ void positionChanged();
+ void movingChanged();
+ void flickingChanged();
+ void movementStarted();
+ void movementEnded();
+ void flickStarted();
+ void flickEnded();
+ void velocityDecayChanged(int);
+ void velocityChanged(qreal, qreal);
+ void isAtBoundaryChanged();
+ void pageChanged();
+
+protected:
+ virtual bool mouseFilter(QGraphicsSceneMouseEvent *);
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+ qreal visibleX() const;
+ qreal visibleY() const;
+
+protected Q_SLOTS:
+ virtual void ticked();
+ void movementStarting();
+ void movementEnding();
+ void heightChange();
+ void widthChange();
+
+protected:
+ virtual qreal minXExtent() const;
+ virtual qreal minYExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual qreal maxYExtent() const;
+ int vWidth() const;
+ int vHeight() const;
+ virtual void viewportMoved();
+ bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
+
+ bool xflick() const;
+ bool yflick() const;
+
+protected:
+ QFxFlickable(QFxFlickablePrivate &dd, QFxItem *parent);
+
+private:
+ Q_DISABLE_COPY(QFxFlickable)
+ Q_DECLARE_PRIVATE(QFxFlickable)
+};
+QML_DECLARE_TYPE(QFxFlickable);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxflickable_p.h b/src/declarative/fx/qfxflickable_p.h
new file mode 100644
index 0000000..ebd0327
--- /dev/null
+++ b/src/declarative/fx/qfxflickable_p.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXFLICKABLE_P_H
+#define QFXFLICKABLE_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 "qdatetime.h"
+#include "qfxflickable.h"
+#include "qfxitem_p.h"
+#include "qml.h"
+#include "qmltimelinevalueproxy.h"
+#include "private/qmlanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class ElasticValue : public QAbstractAnimation {
+ Q_OBJECT
+public:
+ ElasticValue(QmlTimeLineValue &);
+ void setValue(qreal to);
+ void clear();
+
+ virtual int duration() const { return 10000; }
+
+protected:
+ virtual void updateCurrentTime(int);
+
+Q_SIGNALS:
+ void updated();
+
+private:
+ qreal _to;
+ qreal _myValue;
+ qreal _velocity;
+ QmlTimeLineValue &_value;
+ QTime _startTime;
+};
+
+class QFxFlickablePrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxFlickable)
+
+public:
+ QFxFlickablePrivate();
+ void init();
+ virtual void fixupX();
+ virtual void fixupY();
+ void updateBeginningEnd();
+
+public:
+ QFxItem *_flick;
+ QmlTimeLineValueProxy<QFxItem> _moveX;
+ QmlTimeLineValueProxy<QFxItem> _moveY;
+ QmlTimeLine _tl;
+ int vWidth;
+ int vHeight;
+ bool overShoot;
+ bool flicked;
+ bool moving;
+ bool stealMouse;
+ bool pressed;
+ QTime lastPosTime;
+ QPointF lastPos;
+ QPointF pressPos;
+ qreal pressX;
+ qreal pressY;
+ qreal velocityX;
+ qreal velocityY;
+ QTime pressTime;
+ QmlTimeLineEvent fixupXEvent;
+ QmlTimeLineEvent fixupYEvent;
+ int maxVelocity;
+ bool locked;
+ QFxFlickable::DragMode dragMode;
+ ElasticValue elasticY;
+ ElasticValue elasticX;
+ QTime velocityTime;
+ QPointF lastFlickablePosition;
+ int velocityDecay;
+
+ void updateVelocity();
+ struct Velocity : public QmlTimeLineValue
+ {
+ Velocity(QFxFlickablePrivate *p)
+ : parent(p) {}
+ virtual void setValue(qreal v) {
+ QmlTimeLineValue::setValue(v);
+ parent->updateVelocity();
+ }
+ QFxFlickablePrivate *parent;
+ };
+ Velocity xVelocity;
+ Velocity yVelocity;
+ int vTime;
+ QmlTimeLine velocityTimeline;
+ bool atXEnd;
+ bool atXBeginning;
+ qreal pageXPosition;
+ qreal pageWidth;
+ bool atYEnd;
+ bool atYBeginning;
+ qreal pageYPosition;
+ qreal pageHeight;
+
+ void handleMousePressEvent(QGraphicsSceneMouseEvent *);
+ void handleMouseMoveEvent(QGraphicsSceneMouseEvent *);
+ void handleMouseReleaseEvent(QGraphicsSceneMouseEvent *);
+
+ // flickableData property
+ void data_removeAt(int);
+ int data_count() const;
+ void data_append(QObject *);
+ void data_insert(int, QObject *);
+ QObject *data_at(int) const;
+ void data_clear();
+ QML_DECLARE_LIST_PROXY(QFxFlickablePrivate, QObject *, data);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/fx/qfxflipable.cpp b/src/declarative/fx/qfxflipable.cpp
new file mode 100644
index 0000000..24ae428
--- /dev/null
+++ b/src/declarative/fx/qfxflipable.cpp
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxflipable.h"
+#include "private/qfxitem_p.h"
+#include "qfxtransform.h"
+#include <QtDeclarative/qmlinfo.h>
+
+QML_DEFINE_TYPE(QFxFlipable,Flipable);
+
+class QFxFlipablePrivate : public QFxItemPrivate
+{
+public:
+ QFxFlipablePrivate() : current(QFxFlipable::Front), front(0), back(0), axis(0), rotation(0) {}
+
+ void setBackTransform();
+ void _q_updateAxis();
+
+ QFxFlipable::Side current;
+ QFxItem *front;
+ QFxItem *back;
+ QFxAxis *axis;
+ QFxRotation3D axisRotation;
+ qreal rotation;
+};
+
+/*!
+ \qmlclass Flipable QFxFlipable
+ \brief The Flipable item provides a surface that can be flipped.
+ \inherits Item
+
+ Flipable allows you to specify a front and a back and then flip between those sides.
+
+ \qml
+Flipable {
+ id: flipable
+ width: 40
+ height: 40
+ axis: Axis {
+ startX: 20
+ startY: 0
+ endX: 20
+ endY: 40
+ }
+ front: Image { source: "front.png" }
+ back: Image { source: "back.png" }
+ states: [
+ State {
+ name: "back"
+ SetProperty {
+ target: flipable
+ property: "rotation"
+ value: 180
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumericAnimation {
+ easing: "easeInOutQuad"
+ properties: "rotation"
+ }
+ }
+ ]
+}
+ \endqml
+
+ \image flipable.gif
+*/
+
+/*!
+ \internal
+ \class QFxFlipable
+ \brief The QFxFlipable class provides a flipable surface.
+
+ \ingroup group_widgets
+
+ QFxFlipable allows you to specify a front and a back, as well as an
+ axis for the flip.
+*/
+
+QFxFlipable::QFxFlipable(QFxItem *parent)
+: QFxItem(*(new QFxFlipablePrivate), parent)
+{
+}
+
+QFxFlipable::~QFxFlipable()
+{
+}
+
+/*!
+ \qmlproperty Item Flipable::front
+ \qmlproperty Item Flipable::back
+
+ The front and back sides of the flipable.
+*/
+
+QFxItem *QFxFlipable::front()
+{
+ Q_D(const QFxFlipable);
+ return d->front;
+}
+
+void QFxFlipable::setFront(QFxItem *front)
+{
+ Q_D(QFxFlipable);
+ if (d->front) {
+ qmlInfo(this) << "front is a write-once property";
+ return;
+ }
+ d->front = front;
+ children()->append(d->front);
+ if (Back == d->current)
+ d->front->setOpacity(0.);
+}
+
+QFxItem *QFxFlipable::back()
+{
+ Q_D(const QFxFlipable);
+ return d->back;
+}
+
+void QFxFlipable::setBack(QFxItem *back)
+{
+ Q_D(QFxFlipable);
+ if (d->back) {
+ qmlInfo(this) << "back is a write-once property";
+ return;
+ }
+ d->back = back;
+ children()->append(d->back);
+ if (Front == d->current)
+ d->back->setOpacity(0.);
+ d->setBackTransform();
+}
+
+/*!
+ \qmlproperty Axis Flipable::axis
+
+ The axis to flip around. See the \l Axis documentation for more
+ information on specifying an axis.
+*/
+
+QFxAxis *QFxFlipable::axis()
+{
+ Q_D(QFxFlipable);
+ return d->axis;
+}
+
+void QFxFlipable::setAxis(QFxAxis *axis)
+{
+ Q_D(QFxFlipable);
+ //### disconnect if we are already connected?
+ if (d->axis)
+ disconnect(d->axis, SIGNAL(updated()), this, SLOT(_q_updateAxis()));
+ d->axis = axis;
+ connect(d->axis, SIGNAL(updated()), this, SLOT(_q_updateAxis()));
+ d->_q_updateAxis();
+}
+
+void QFxFlipablePrivate::_q_updateAxis()
+{
+ axisRotation.axis()->setStartX(axis->startX());
+ axisRotation.axis()->setStartY(axis->startY());
+ axisRotation.axis()->setEndX(axis->endX());
+ axisRotation.axis()->setEndY(axis->endY());
+ axisRotation.axis()->setEndZ(axis->endZ());
+
+ setBackTransform();
+}
+
+void QFxFlipablePrivate::setBackTransform()
+{
+ if (!back)
+ return;
+
+ QPointF p1(0, 0);
+ QPointF p2(1, 0);
+ QPointF p3(1, 1);
+
+ axisRotation.setAngle(180);
+ p1 = axisRotation.transform().map(p1);
+ p2 = axisRotation.transform().map(p2);
+ p3 = axisRotation.transform().map(p3);
+ axisRotation.setAngle(rotation);
+
+ QSimpleCanvas::Matrix mat;
+#ifdef QFX_RENDER_OPENGL
+ mat.translate(back->width()/2,back->height()/2, 0);
+ if (back->width() && p1.x() >= p2.x())
+ mat.rotate(180, 0, 1, 0);
+ if (back->height() && p2.y() >= p3.y())
+ mat.rotate(180, 1, 0, 0);
+ mat.translate(-back->width()/2,-back->height()/2, 0);
+#else
+ mat.translate(back->width()/2,back->height()/2);
+ if (back->width() && p1.x() >= p2.x())
+ mat.rotate(180, Qt::YAxis);
+ if (back->height() && p2.y() >= p3.y())
+ mat.rotate(180, Qt::XAxis);
+ mat.translate(-back->width()/2,-back->height()/2);
+#endif
+ back->setTransform(mat);
+}
+
+/*!
+ \qmlproperty real Flipable::rotation
+ The angle to rotate the flipable. For example, to show the back side of the flipable
+ you can set the rotation to 180.
+*/
+qreal QFxFlipable::rotation() const
+{
+ Q_D(const QFxFlipable);
+ return d->rotation;
+}
+
+void QFxFlipable::setRotation(qreal angle)
+{
+ Q_D(QFxFlipable);
+ d->rotation = angle;
+ d->axisRotation.setAngle(angle);
+ setTransform(d->axisRotation.transform());
+
+
+ int simpleAngle = int(angle) % 360;
+
+ Side newSide;
+ if (simpleAngle < 91 || simpleAngle > 270) {
+ newSide = Front;
+ } else {
+ newSide = Back;
+ }
+
+ if (newSide != d->current) {
+ d->current = newSide;
+ if (d->front)
+ d->front->setOpacity((d->current==Front)?1.:0.);
+ if (d->back)
+ d->back->setOpacity((d->current==Back)?1.:0.);
+ emit sideChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration Flipable::side
+
+ The side of the Flippable currently visible. Possible values are \c
+ Front and \c Back.
+*/
+QFxFlipable::Side QFxFlipable::side() const
+{
+ Q_D(const QFxFlipable);
+ return d->current;
+}
+
+//in some cases the user may want to specify a more complex transformation.
+//in that case, we still allow the generic use of transform.
+//(the logic here should be kept in sync with setBackTransform and setRotation)
+void QFxFlipable::transformChanged(const QSimpleCanvas::Matrix &trans)
+{
+ Q_D(QFxFlipable);
+ QPointF p1(0, 0);
+ QPointF p2(1, 0);
+ QPointF p3(1, 1);
+
+ p1 = trans.map(p1);
+ p2 = trans.map(p2);
+ p3 = trans.map(p3);
+
+ qreal cross = (p1.x() - p2.x()) * (p3.y() - p2.y()) -
+ (p1.y() - p2.y()) * (p3.x() - p2.x());
+
+ Side newSide;
+ if (cross > 0) {
+ newSide = Back;
+ } else {
+ newSide = Front;
+ }
+
+ if (newSide != d->current) {
+ d->current = newSide;
+ if (d->current==Back) {
+ QSimpleCanvas::Matrix mat;
+#ifdef QFX_RENDER_OPENGL
+ mat.translate(d->back->width()/2,d->back->height()/2, 0);
+ if (d->back->width() && p1.x() >= p2.x())
+ mat.rotate(180, 0, 1, 0);
+ if (d->back->height() && p2.y() >= p3.y())
+ mat.rotate(180, 1, 0, 0);
+ mat.translate(-d->back->width()/2,-d->back->height()/2, 0);
+#else
+ mat.translate(d->back->width()/2,d->back->height()/2);
+ if (d->back->width() && p1.x() >= p2.x())
+ mat.rotate(180, Qt::YAxis);
+ if (d->back->height() && p2.y() >= p3.y())
+ mat.rotate(180, Qt::XAxis);
+ mat.translate(-d->back->width()/2,-d->back->height()/2);
+#endif
+ d->back->setTransform(mat);
+ }
+ if (d->front)
+ d->front->setOpacity((d->current==Front)?1.:0.);
+ if (d->back)
+ d->back->setOpacity((d->current==Back)?1.:0.);
+ emit sideChanged();
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qfxflipable.cpp"
diff --git a/src/declarative/fx/qfxflipable.h b/src/declarative/fx/qfxflipable.h
new file mode 100644
index 0000000..ef1832e
--- /dev/null
+++ b/src/declarative/fx/qfxflipable.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXFLIPABLE_H
+#define QFXFLIPABLE_H
+
+#include <QObject>
+#include <QTransform>
+#if defined(QFX_RENDER_OPENGL)
+#include <QtGui/qmatrix4x4.h>
+#endif
+#include <qfxitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QFxAxis;
+class QFxFlipablePrivate;
+class Q_DECLARATIVE_EXPORT QFxFlipable : public QFxItem
+{
+ Q_OBJECT
+
+ Q_ENUMS(Side);
+ Q_PROPERTY(QFxItem *front READ front WRITE setFront)
+ Q_PROPERTY(QFxItem *back READ back WRITE setBack)
+ Q_PROPERTY(QFxAxis *axis READ axis WRITE setAxis)
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation)
+ Q_PROPERTY(Side side READ side NOTIFY sideChanged)
+public:
+ QFxFlipable(QFxItem *parent=0);
+ ~QFxFlipable();
+
+ QFxItem *front();
+ void setFront(QFxItem *);
+
+ QFxItem *back();
+ void setBack(QFxItem *);
+
+ QFxAxis *axis();
+ void setAxis(QFxAxis *axis);
+
+ qreal rotation() const;
+ void setRotation(qreal angle);
+
+ enum Side { Front, Back };
+ Side side() const;
+
+protected:
+ virtual void transformChanged(const QSimpleCanvas::Matrix &);
+
+Q_SIGNALS:
+ void sideChanged();
+
+private:
+ Q_PRIVATE_SLOT(d_func(), void _q_updateAxis())
+ Q_DISABLE_COPY(QFxFlipable)
+ Q_DECLARE_PRIVATE(QFxFlipable)
+};
+QML_DECLARE_TYPE(QFxFlipable);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXFLIPABLE_H
diff --git a/src/declarative/fx/qfxfocuspanel.cpp b/src/declarative/fx/qfxfocuspanel.cpp
new file mode 100644
index 0000000..5d62e66
--- /dev/null
+++ b/src/declarative/fx/qfxfocuspanel.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxfocuspanel.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxFocusPanel,FocusPanel);
+
+/*!
+ \qmlclass FocusPanel
+ \brief The FocusPanel object 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}.
+*/
+
+/*!
+ \internal
+ \class QFxFocusPanel
+*/
+
+QFxFocusPanel::QFxFocusPanel(QFxItem *parent) :
+ QFxItem(parent)
+{
+ setOptions(IsFocusPanel);
+}
+
+QFxFocusPanel::~QFxFocusPanel()
+{
+}
+
+/*!
+ \qmlproperty bool FocusPanel::active
+
+ Sets whether the object is the active focus panel.
+*/
+
+bool QFxFocusPanel::isActive() const
+{
+ QSimpleCanvas *canvas = QSimpleCanvasItem::canvas();
+ if (canvas)
+ return canvas->activeFocusPanel() == this;
+ else
+ return false;
+}
+
+void QFxFocusPanel::setActive(bool a)
+{
+ setActiveFocusPanel(a);
+}
+
+void QFxFocusPanel::activePanelInEvent()
+{
+ QFxItem::activePanelInEvent();
+ emit activeChanged();
+}
+
+void QFxFocusPanel::activePanelOutEvent()
+{
+ QFxItem::activePanelOutEvent();
+ emit activeChanged();
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxfocuspanel.h b/src/declarative/fx/qfxfocuspanel.h
new file mode 100644
index 0000000..38f7a15
--- /dev/null
+++ b/src/declarative/fx/qfxfocuspanel.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXFOCUSPANEL_H
+#define QFXFOCUSPANEL_H
+
+#include <qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QFxFocusPanel : public QFxItem
+{
+ Q_OBJECT
+ Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
+public:
+ QFxFocusPanel(QFxItem *parent=0);
+ virtual ~QFxFocusPanel();
+
+ bool isActive() const;
+ void setActive(bool);
+
+Q_SIGNALS:
+ void activeChanged();
+
+protected:
+ virtual void activePanelInEvent();
+ virtual void activePanelOutEvent();
+
+private:
+ Q_DISABLE_COPY(QFxFocusPanel)
+};
+
+QML_DECLARE_TYPE(QFxFocusPanel);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXFOCUSPANEL_H
diff --git a/src/declarative/fx/qfxfocusrealm.cpp b/src/declarative/fx/qfxfocusrealm.cpp
new file mode 100644
index 0000000..07849fa
--- /dev/null
+++ b/src/declarative/fx/qfxfocusrealm.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxfocusrealm.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxFocusRealm,FocusRealm);
+
+/*!
+ \qmlclass FocusRealm
+ \brief The FocusRealm object explicitly creates a focus realm.
+ \inherits Item
+
+ Focus realms assist in keyboard focus handling when building reusable QML
+ components. All the details are covered in the
+ \l {qmlfocus}{keyboard focus documentation}.
+*/
+
+/*!
+ \internal
+ \class QFxFocusRealm
+*/
+
+QFxFocusRealm::QFxFocusRealm(QFxItem *parent) :
+ QFxItem(parent)
+{
+ setOptions(IsFocusRealm);
+}
+
+QFxFocusRealm::~QFxFocusRealm()
+{
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxfocusrealm.h b/src/declarative/fx/qfxfocusrealm.h
new file mode 100644
index 0000000..6c35405
--- /dev/null
+++ b/src/declarative/fx/qfxfocusrealm.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXFOCUSREALM_H
+#define QFXFOCUSREALM_H
+
+#include <qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QFxFocusRealm : public QFxItem
+{
+ Q_OBJECT
+public:
+ QFxFocusRealm(QFxItem *parent=0);
+ virtual ~QFxFocusRealm();
+};
+
+QML_DECLARE_TYPE(QFxFocusRealm);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXFOCUSREALM_H
diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp
new file mode 100644
index 0000000..5156d06
--- /dev/null
+++ b/src/declarative/fx/qfxgridview.cpp
@@ -0,0 +1,1399 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxvisualitemmodel.h"
+#include "qlistmodelinterface.h"
+#include "qmlfollow.h"
+#include "private/qfxflickable_p.h"
+#include "qfxgridview.h"
+
+QT_BEGIN_NAMESPACE
+
+class QFxGridViewAttached : public QObject
+{
+ Q_OBJECT
+public:
+ QFxGridViewAttached(QObject *parent)
+ : QObject(parent), m_isCurrent(false), m_delayRemove(false) {}
+ ~QFxGridViewAttached() {
+ attachedProperties.remove(parent());
+ }
+
+ Q_PROPERTY(QFxGridView *view READ view);
+ QFxGridView *view() { return m_view; }
+
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged);
+ bool isCurrentItem() const { return m_isCurrent; }
+ void setIsCurrentItem(bool c) {
+ if (m_isCurrent != c) {
+ m_isCurrent = c;
+ emit currentItemChanged();
+ }
+ }
+
+ Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged);
+ bool delayRemove() const { return m_delayRemove; }
+ void setDelayRemove(bool delay) {
+ if (m_delayRemove != delay) {
+ m_delayRemove = delay;
+ emit delayRemoveChanged();
+ }
+ }
+
+ static QFxGridViewAttached *properties(QObject *obj) {
+ QFxGridViewAttached *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QFxGridViewAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+ }
+
+ void emitAdd() { emit add(); }
+ void emitRemove() { emit remove(); }
+
+signals:
+ void currentItemChanged();
+ void delayRemoveChanged();
+ void add();
+ void remove();
+
+public:
+ QFxGridView *m_view;
+ bool m_isCurrent;
+ bool m_delayRemove;
+
+ static QHash<QObject*, QFxGridViewAttached*> attachedProperties;
+};
+
+QHash<QObject*, QFxGridViewAttached*> QFxGridViewAttached::attachedProperties;
+
+
+//----------------------------------------------------------------------------
+
+class FxGridItem
+{
+public:
+ FxGridItem(QFxItem *i, QFxGridView *v) : item(i), view(v) {
+ attached = QFxGridViewAttached::properties(item);
+ attached->m_view = view;
+ }
+ ~FxGridItem() {}
+
+ qreal rowPos() const { return (view->flow() == QFxGridView::LeftToRight ? item->y() : item->x()); }
+ qreal colPos() const { return (view->flow() == QFxGridView::LeftToRight ? item->x() : item->y()); }
+ qreal endRowPos() const {
+ return (view->flow() == QFxGridView::LeftToRight
+ ? item->y() + (item->height() > 0 ? item->height() : 1)
+ : item->x() + (item->width() > 0 ? item->width() : 1)) - 1;
+ }
+ void setPosition(qreal col, qreal row) {
+ if (view->flow() == QFxGridView::LeftToRight) {
+ item->setPos(QPointF(col, row));
+ } else {
+ item->setPos(QPointF(row, col));
+ }
+ }
+
+ QFxItem *item;
+ QFxGridView *view;
+ QFxGridViewAttached *attached;
+ int index;
+};
+
+//----------------------------------------------------------------------------
+
+class QFxGridViewPrivate : public QFxFlickablePrivate
+{
+ Q_DECLARE_PUBLIC(QFxGridView);
+
+public:
+ QFxGridViewPrivate()
+ : model(0), currentItem(0), tmpCurrent(0), flow(QFxGridView::LeftToRight)
+ , visiblePos(0), visibleIndex(0) , currentIndex(-1)
+ , cellWidth(100), cellHeight(100), columns(1)
+ , highlightComponent(0), highlight(0), trackedItem(0)
+ , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
+ , keyPressed(false), ownModel(false), wrap(false), autoHighlight(true)
+ , fixCurrentVisibility(false) {}
+
+ void init();
+ void clear();
+ FxGridItem *getItem(int modelIndex);
+ FxGridItem *createItem(int modelIndex);
+ void releaseItem(FxGridItem *item);
+ void refill(qreal from, qreal to);
+
+ void updateGrid();
+ void layout(bool removed=false);
+ void updateTrackedItem();
+ void createHighlight();
+ void updateHighlight();
+ void updateCurrent(int modelIndex);
+
+ 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;
+ }
+
+ qreal position() const {
+ Q_Q(const QFxGridView);
+ return flow == QFxGridView::LeftToRight ? q->yPosition() : q->xPosition();
+ }
+ void setPosition(qreal pos) {
+ Q_Q(QFxGridView);
+ if (flow == QFxGridView::LeftToRight)
+ q->setYPosition(pos);
+ else
+ q->setXPosition(pos);
+ }
+ int size() const {
+ Q_Q(const QFxGridView);
+ return flow == QFxGridView::LeftToRight ? q->height() : q->width();
+ }
+ qreal startPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty())
+ pos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
+ return pos;
+ }
+
+ qreal endPosition() const {
+ qreal pos = 0;
+ if (model && model->count())
+ pos = rowPosAt(model->count() - 1) + rowSize();
+ return pos;
+ }
+
+ bool isValid() const {
+ return model && model->count() && (!ownModel || model->delegate());
+ }
+
+ int rowSize() const {
+ return flow == QFxGridView::LeftToRight ? cellHeight : cellWidth;
+ }
+ int colSize() const {
+ return flow == QFxGridView::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();
+ }
+ }
+ 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();
+ }
+ }
+ return 0;
+ }
+
+ // 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
+ }
+
+ // 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) {
+ qDebug() << "index" << visibleIndex << i << listItem->index;
+ for (int j = 0; j < visibleItems.count(); j++)
+ qDebug() << " index" << j << "item index" << visibleItems.at(j)->index;
+ abort();
+ }
+ }
+ }
+
+ QFxVisualItemModel *model;
+ QVariant modelVariant;
+ QList<FxGridItem*> visibleItems;
+ FxGridItem *currentItem;
+ QFxItem *tmpCurrent;
+ QFxGridView::Flow flow;
+ int visiblePos;
+ int visibleIndex;
+ int currentIndex;
+ int cellWidth;
+ int cellHeight;
+ int columns;
+ QmlComponent *highlightComponent;
+ FxGridItem *highlight;
+ FxGridItem *trackedItem;
+ enum MovementReason { Other, Key, Mouse };
+ MovementReason moveReason;
+ int buffer;
+ QmlFollow *highlightXAnimator;
+ QmlFollow *highlightYAnimator;
+
+ int keyPressed : 1;
+ int ownModel : 1;
+ int wrap : 1;
+ int autoHighlight : 1;
+ int fixCurrentVisibility : 1;
+};
+
+void QFxGridViewPrivate::init()
+{
+ Q_Q(QFxGridView);
+ q->setOptions(QFxGridView::IsFocusRealm);
+ QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(sizeChange()));
+ QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(sizeChange()));
+}
+
+void QFxGridViewPrivate::clear()
+{
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ visiblePos = 0;
+ visibleIndex = 0;
+ if (currentItem) {
+ FxGridItem *tmpItem = currentItem;
+ currentItem = 0;
+ currentIndex = -1;
+ releaseItem(tmpItem);
+ }
+ createHighlight();
+ trackedItem = 0;
+}
+
+FxGridItem *QFxGridViewPrivate::getItem(int modelIndex)
+{
+ if (currentItem && modelIndex == currentIndex)
+ return currentItem;
+ if (FxGridItem *listItem = visibleItem(modelIndex))
+ return listItem;
+ return createItem(modelIndex);
+}
+
+FxGridItem *QFxGridViewPrivate::createItem(int modelIndex)
+{
+ Q_Q(QFxGridView);
+ // create object
+ FxGridItem *listItem = 0;
+ if (QFxItem *item = model->item(modelIndex, false)) {
+ listItem = new FxGridItem(item, q);
+ listItem->index = modelIndex;
+ // complete
+ model->completeItem();
+ listItem->item->setZ(modelIndex + 1);
+ listItem->item->setParent(q->viewport());
+ }
+ return listItem;
+}
+
+
+void QFxGridViewPrivate::releaseItem(FxGridItem *item)
+{
+ Q_Q(QFxGridView);
+ if (item != currentItem) {
+ if (trackedItem == item) {
+ QObject::disconnect(trackedItem->item, SIGNAL(topChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, SIGNAL(leftChanged()), q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+ model->release(item->item);
+ delete item;
+ }
+}
+
+void QFxGridViewPrivate::refill(qreal from, qreal to)
+{
+ Q_Q(QFxGridView);
+ if (!isValid() || !q->isComponentComplete())
+ return;
+
+ from -= buffer;
+ to += buffer;
+ bool changed = false;
+
+ int colPos = 0;
+ int rowPos = 0;
+ int modelIndex = 0;
+ 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;
+ }
+
+ FxGridItem *item = 0;
+ while (modelIndex < model->count() && rowPos <= to) {
+ //qDebug() << "refill: append item" << modelIndex;
+ item = getItem(modelIndex);
+ item->setPosition(colPos, rowPos);
+ visibleItems.append(item);
+ colPos += colSize();
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ rowPos += rowSize();
+ }
+ ++modelIndex;
+ changed = true;
+ }
+
+ if (visibleItems.count()) {
+ rowPos = visibleItems.first()->rowPos();
+ colPos = visibleItems.first()->colPos() - colSize();
+ if (colPos < 0) {
+ colPos = colSize() * (columns - 1);
+ rowPos -= rowSize();
+ }
+ }
+ while (visibleIndex > 0 && rowPos + rowSize() - 1 >= from){
+ //qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
+ item = getItem(visibleIndex-1);
+ --visibleIndex;
+ item->setPosition(colPos, rowPos);
+ visibleItems.prepend(item);
+ colPos -= colSize();
+ if (colPos < 0) {
+ colPos = colSize() * (columns - 1);
+ rowPos -= rowSize();
+ }
+ changed = true;
+ }
+
+ while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endRowPos() < from) {
+ 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() > to) {
+ if (item->attached->delayRemove())
+ break;
+ //qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+ visibleItems.removeLast();
+ releaseItem(item);
+ changed = true;
+ }
+ if (changed) {
+ if (flow == QFxGridView::LeftToRight)
+ q->setViewportHeight(endPosition() - startPosition());
+ else
+ q->setViewportWidth(endPosition() - startPosition());
+ }
+}
+
+void QFxGridViewPrivate::updateGrid()
+{
+ Q_Q(QFxGridView);
+ columns = (int)qMax((flow == QFxGridView::LeftToRight ? q->width() : q->height()) / colSize(), 1.);
+ if (isValid()) {
+ if (flow == QFxGridView::LeftToRight)
+ q->setViewportHeight(endPosition() - startPosition());
+ else
+ q->setViewportWidth(endPosition() - startPosition());
+ }
+}
+
+void QFxGridViewPrivate::layout(bool removed)
+{
+ Q_Q(QFxGridView);
+ if (visibleItems.count()) {
+ qreal rowPos = visibleItems.first()->rowPos();
+ qreal colPos = visibleItems.first()->colPos();
+ if (visibleIndex % columns != 0) {
+ if (removed)
+ rowPos -= rowSize();
+ colPos = (visibleIndex % columns) * colSize();
+ visibleItems.first()->setPosition(colPos, rowPos);
+ } else if (colPos != 0) {
+ colPos = 0;
+ 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);
+ }
+ }
+ q->refill();
+ q->trackedPositionChanged();
+ updateHighlight();
+ if (flow == QFxGridView::LeftToRight) {
+ q->setViewportHeight(endPosition() - startPosition());
+ fixupY();
+ } else {
+ q->setViewportWidth(endPosition() - startPosition());
+ fixupX();
+ }
+}
+
+void QFxGridViewPrivate::updateTrackedItem()
+{
+ Q_Q(QFxGridView);
+ FxGridItem *item = currentItem;
+ if (highlight)
+ item = highlight;
+
+ if (trackedItem && item != trackedItem) {
+ QObject::disconnect(trackedItem->item, SIGNAL(topChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, SIGNAL(leftChanged()), q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+
+ if (!trackedItem && item) {
+ trackedItem = item;
+ QObject::connect(trackedItem->item, SIGNAL(topChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::connect(trackedItem->item, SIGNAL(leftChanged()), q, SLOT(trackedPositionChanged()));
+ q->trackedPositionChanged();
+ }
+ if (trackedItem)
+ q->trackedPositionChanged();
+}
+
+void QFxGridViewPrivate::createHighlight()
+{
+ Q_Q(QFxGridView);
+ if (highlight) {
+ if (trackedItem == highlight)
+ trackedItem = 0;
+ delete highlight->item;
+ delete highlight;
+ highlight = 0;
+ delete highlightXAnimator;
+ delete highlightYAnimator;
+ highlightXAnimator = 0;
+ highlightYAnimator = 0;
+ }
+
+ if (!highlightComponent)
+ return;
+
+ if (currentItem) {
+ QmlContext *highlightContext = new QmlContext(qmlContext(q));
+ QObject *nobj = highlightComponent->create(highlightContext);
+ if (nobj) {
+ highlightContext->setParent(nobj);
+ QFxItem *item = qobject_cast<QFxItem *>(nobj);
+ if (item) {
+ item->setParent(q->viewport());
+ highlight = new FxGridItem(item, q);
+ highlightXAnimator = new QmlFollow(q);
+ highlightXAnimator->setTarget(QmlMetaProperty(highlight->item, QLatin1String("x")));
+ highlightXAnimator->setSpring(3);
+ highlightXAnimator->setDamping(0.3);
+ highlightXAnimator->setEnabled(autoHighlight);
+ highlightYAnimator = new QmlFollow(q);
+ highlightYAnimator->setTarget(QmlMetaProperty(highlight->item, QLatin1String("y")));
+ highlightYAnimator->setSpring(3);
+ highlightYAnimator->setDamping(0.3);
+ highlightYAnimator->setEnabled(autoHighlight);
+ } else {
+ delete highlightContext;
+ }
+ }
+ }
+}
+
+void QFxGridViewPrivate::updateHighlight()
+{
+ if ((!currentItem && highlight) || (currentItem && !highlight))
+ createHighlight();
+ updateTrackedItem();
+ if (currentItem && autoHighlight && highlight) {
+ // auto-update highlight
+ highlightXAnimator->setSourceValue(currentItem->item->x());
+ highlightYAnimator->setSourceValue(currentItem->item->y());
+ highlight->item->setWidth(currentItem->item->width());
+ highlight->item->setHeight(currentItem->item->height());
+ }
+}
+
+void QFxGridViewPrivate::updateCurrent(int modelIndex)
+{
+ Q_Q(QFxGridView);
+ if (!isValid() || modelIndex < 0 || modelIndex >= model->count()) {
+ if (currentItem) {
+ FxGridItem *item = currentItem;
+ currentItem = 0;
+ currentIndex = 0;
+ updateHighlight();
+ releaseItem(item);
+ emit q->currentIndexChanged();
+ }
+ return;
+ }
+
+ if (currentItem && currentIndex == modelIndex) {
+ updateHighlight();
+ return;
+ }
+
+ if (tmpCurrent) {
+ delete tmpCurrent;
+ tmpCurrent = 0;
+ }
+ int oldCurrentIndex = currentIndex;
+ FxGridItem *oldCurrentItem = currentItem;
+ currentIndex = -1;
+ currentItem = visibleItem(modelIndex);
+ if (!currentItem) {
+ currentItem = getItem(modelIndex);
+ currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex));
+ }
+ currentIndex = modelIndex;
+ fixCurrentVisibility = true;
+ if (oldCurrentItem && oldCurrentItem->item != currentItem->item)
+ oldCurrentItem->attached->setIsCurrentItem(false);
+ currentItem->item->setFocus(true);
+ currentItem->attached->setIsCurrentItem(true);
+ updateHighlight();
+ emit q->currentIndexChanged();
+ // Release the old current item
+ if (oldCurrentItem && !visibleItem(oldCurrentIndex))
+ releaseItem(oldCurrentItem);
+}
+
+//----------------------------------------------------------------------------
+
+/*!
+ \qmlclass GridView
+ \inherits Flickable
+ \brief The GridView item provides a grid view of items provided by a model.
+
+ The model is typically provided by a QAbstractListModel "C++ model object",
+ but can also be created directly in QML.
+
+ The items are laid out top to bottom (vertically) or left to right (horizontally)
+ and may be flicked to scroll.
+
+ The below example creates a very simple grid, using a QML model.
+
+ \image gridview.png
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml 3
+
+ The model is defined as a ListModel using QML:
+ \quotefile doc/src/snippets/declarative/gridview/dummydata/ContactModel.qml
+
+ In this case ListModel is a handy way for us to test our UI. In practice
+ the model would be implemented in C++, or perhaps via a SQL data source.
+
+
+*/
+QFxGridView::QFxGridView(QFxItem *parent)
+ : QFxFlickable(*(new QFxGridViewPrivate), parent)
+{
+ Q_D(QFxGridView);
+ d->init();
+}
+
+QFxGridView::~QFxGridView()
+{
+ Q_D(QFxGridView);
+ if (d->ownModel)
+ delete d->model;
+}
+
+/*!
+ \qmlproperty model GridView::model
+ This property holds the model providing data for the grid.
+
+ The model provides a set of data that is used to create the items
+ for the view. For large or dynamic datasets the model is usually
+ provided by a C++ model object. The C++ model object must be a \l
+ {QAbstractItemModel} subclass, a VisualModel, or a simple list.
+*/
+QVariant QFxGridView::model() const
+{
+ Q_D(const QFxGridView);
+ return d->modelVariant;
+}
+
+void QFxGridView::setModel(const QVariant &model)
+{
+ Q_D(QFxGridView);
+ 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)));
+ }
+ d->clear();
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QFxVisualItemModel *vim = 0;
+ if (object && (vim = qobject_cast<QFxVisualItemModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QFxVisualItemModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ d->model->setModel(model);
+ }
+ if (d->model) {
+ if (d->currentIndex >= d->model->count() || d->currentIndex < 0)
+ setCurrentIndex(0);
+ else
+ d->updateCurrent(d->currentIndex);
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ refill();
+ emit countChanged();
+ }
+}
+
+/*!
+ \qmlproperty component GridView::delegate
+
+ The delegate provides a template describing what each item in the view should look and act like.
+
+ Here is an example delegate:
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml 0
+*/
+QmlComponent *QFxGridView::delegate() const
+{
+ Q_D(const QFxGridView);
+ return d->model ? d->model->delegate() : 0;
+}
+
+void QFxGridView::setDelegate(QmlComponent *delegate)
+{
+ Q_D(QFxGridView);
+ if (!d->ownModel) {
+ d->model = new QFxVisualItemModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ d->model->setDelegate(delegate);
+ d->updateCurrent(d->currentIndex);
+ refill();
+}
+
+/*!
+ \qmlproperty int GridView::currentIndex
+ \qmlproperty Item GridView::current
+
+ \c currentIndex holds the index of the current item.
+ \c current is the current item. Note that the position of the current item
+ may only be approximate until it becomes visible in the view.
+*/
+int QFxGridView::currentIndex() const
+{
+ Q_D(const QFxGridView);
+ return d->currentIndex;
+}
+
+void QFxGridView::setCurrentIndex(int index)
+{
+ Q_D(QFxGridView);
+ if (d->isValid() && index != d->currentIndex && index < d->model->count() && index >= 0)
+ d->updateCurrent(index);
+ else
+ d->currentIndex = index;
+}
+
+QFxItem *QFxGridView::currentItem()
+{
+ Q_D(QFxGridView);
+ if (!d->currentItem) {
+ // Always return something valid
+ if (!d->tmpCurrent)
+ d->tmpCurrent = new QFxItem(viewport());
+ return d->tmpCurrent;
+ }
+ return d->currentItem->item;
+}
+
+/*!
+ \qmlproperty int GridView::count
+ This property holds the number of items in the view.
+*/
+int QFxGridView::count() const
+{
+ Q_D(const QFxGridView);
+ if (d->model)
+ return d->model->count();
+ return 0;
+}
+
+/*!
+ \qmlproperty component GridView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component will be created for each view.
+ The geometry of the resultant component instance will be managed by the view
+ so as to stay with the current item, unless the autoHighlight property is false.
+
+ The below example demonstrates how to make a simple highlight:
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml 1
+
+ \sa autoHighlight
+*/
+QmlComponent *QFxGridView::highlight() const
+{
+ Q_D(const QFxGridView);
+ return d->highlightComponent;
+}
+
+void QFxGridView::setHighlight(QmlComponent *highlight)
+{
+ Q_D(QFxGridView);
+ delete d->highlightComponent;
+ d->highlightComponent = highlight;
+ d->updateCurrent(d->currentIndex);
+}
+
+/*!
+ \qmlproperty component GridView::autoHighlight
+ This property sets whether the highlight is managed by the view.
+
+ If autoHighlight is true, the highlight will be moved smoothly
+ to follow the current item. If autoHighlight is false, the
+ highlight will not be moved by the view, and must be implemented
+ by the highlight component, for example:
+
+ \code
+ Component {
+ id: Highlight
+ Rect {
+ id: Wrapper; color: "lightsteelblue"; radius: 4; width: 320; height: 60 >
+ y: Follow { source: Wrapper.GridView.view.current.y; spring: 3; damping: 0.2 }
+ x: Follow { source: Wrapper.GridView.view.current.x; spring: 3; damping: 0.2 }
+ }
+ }
+ \endcode
+*/
+bool QFxGridView::autoHighlight() const
+{
+ Q_D(const QFxGridView);
+ return d->autoHighlight;
+}
+
+void QFxGridView::setAutoHighlight(bool autoHighlight)
+{
+ Q_D(QFxGridView);
+ d->autoHighlight = autoHighlight;
+ if (d->highlightXAnimator) {
+ d->highlightXAnimator->setEnabled(d->autoHighlight);
+ d->highlightYAnimator->setEnabled(d->autoHighlight);
+ }
+ d->updateHighlight();
+}
+
+/*!
+ \qmlproperty enumeration GridView::flow
+ This property holds the flow of the grid.
+
+ Possible values are \c LeftToRight (default) and \c TopToBottom.
+
+ If \a flow is \c LeftToRight, the view will scroll vertically.
+ If \a flow is \c TopToBottom, the view will scroll horizontally.
+*/
+QFxGridView::Flow QFxGridView::flow() const
+{
+ Q_D(const QFxGridView);
+ return d->flow;
+}
+
+void QFxGridView::setFlow(Flow flow)
+{
+ Q_D(QFxGridView);
+ if (d->flow != flow) {
+ d->flow = flow;
+ if (d->flow == LeftToRight)
+ setViewportWidth(-1);
+ else
+ setViewportHeight(-1);
+ d->clear();
+ d->updateGrid();
+ refill();
+ d->updateCurrent(d->currentIndex);
+ }
+}
+
+/*!
+ \qmlproperty bool GridView::wrap
+ This property holds whether the grid wraps key navigation
+
+ If this property is true then key presses to move off of one end of the grid will cause the
+ selection to jump to the other side.
+*/
+bool QFxGridView::isWrapEnabled() const
+{
+ Q_D(const QFxGridView);
+ return d->wrap;
+}
+
+void QFxGridView::setWrapEnabled(bool wrap)
+{
+ Q_D(QFxGridView);
+ d->wrap = wrap;
+}
+
+/*!
+ \qmlproperty int GridView::cacheBuffer
+ This property holds the number of off-screen pixels to cache.
+
+ This property determines the number of pixels above the top of the view
+ and below the bottom of the view to cache. Setting this value can make
+ scrolling the view smoother at the expense of additional memory usage.
+*/
+
+/*!
+ \property QFxGridView::cacheBuffer
+ \brief sets the number of off-screen pixels to cache.
+
+ This property determines the number of pixels above the top of the view
+ and below the bottom of the view to cache. Setting this value can make
+ scrolling the view smoother at the expense of additional memory usage.
+*/
+int QFxGridView::cacheBuffer() const
+{
+ Q_D(const QFxGridView);
+ return d->buffer;
+}
+
+void QFxGridView::setCacheBuffer(int buffer)
+{
+ Q_D(QFxGridView);
+ if (d->buffer != buffer) {
+ d->buffer = buffer;
+ if (isComponentComplete())
+ refill();
+ }
+}
+
+/*!
+ \qmlproperty int GridView::cellWidth
+ \qmlproperty int GridView::cellHeight
+
+ These properties holds the width and height of each cell in the grid
+
+ The default sell size is 100x100.
+*/
+int QFxGridView::cellWidth() const
+{
+ Q_D(const QFxGridView);
+ return d->cellWidth;
+}
+
+void QFxGridView::setCellWidth(int cellWidth)
+{
+ Q_D(QFxGridView);
+ if (cellWidth != d->cellWidth && cellWidth > 0) {
+ d->cellWidth = qMax(1, cellWidth);
+ d->updateGrid();
+ emit cellSizeChanged();
+ d->layout();
+ }
+}
+
+int QFxGridView::cellHeight() const
+{
+ Q_D(const QFxGridView);
+ return d->cellHeight;
+}
+
+void QFxGridView::setCellHeight(int cellHeight)
+{
+ Q_D(QFxGridView);
+ if (cellHeight != d->cellHeight && cellHeight > 0) {
+ d->cellHeight = qMax(1, cellHeight);
+ d->updateGrid();
+ emit cellSizeChanged();
+ d->layout();
+ }
+}
+
+void QFxGridView::sizeChange()
+{
+ Q_D(QFxGridView);
+ if (isComponentComplete()) {
+ d->updateGrid();
+ d->layout();
+ }
+}
+
+/*!
+ \reimp
+*/
+void QFxGridView::viewportMoved()
+{
+ QFxFlickable::viewportMoved();
+ refill();
+}
+
+/*!
+ \reimp
+*/
+qreal QFxGridView::minYExtent() const
+{
+ Q_D(const QFxGridView);
+ if (d->flow == QFxGridView::TopToBottom)
+ return QFxFlickable::minYExtent();
+ return -d->startPosition();
+}
+
+/*!
+ \reimp
+*/
+qreal QFxGridView::maxYExtent() const
+{
+ Q_D(const QFxGridView);
+ if (d->flow == QFxGridView::TopToBottom)
+ return QFxFlickable::maxYExtent();
+ return -(d->endPosition() - height());
+}
+
+/*!
+ \reimp
+*/
+qreal QFxGridView::minXExtent() const
+{
+ Q_D(const QFxGridView);
+ if (d->flow == QFxGridView::LeftToRight)
+ return QFxFlickable::minXExtent();
+ return -d->startPosition();
+}
+
+/*!
+ \reimp
+*/
+qreal QFxGridView::maxXExtent() const
+{
+ Q_D(const QFxGridView);
+ if (d->flow == QFxGridView::LeftToRight)
+ return QFxFlickable::maxXExtent();
+ return -(d->endPosition() - height());
+}
+
+/*!
+ \reimp
+*/
+void QFxGridView::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QFxGridView);
+ if (d->model && d->model->count() && !d->locked) {
+ if ((d->flow == QFxGridView::LeftToRight && event->key() == Qt::Key_Up)
+ || (d->flow == QFxGridView::TopToBottom && event->key() == Qt::Key_Left)) {
+ if (currentIndex() >= d->columns || d->wrap) {
+ d->keyPressed = true;
+ d->moveReason = QFxGridViewPrivate::Key;
+ int index = currentIndex() - d->columns;
+ setCurrentIndex(index >= 0 ? index : d->model->count()-1);
+ event->accept();
+ }
+ return;
+ } else if ((d->flow == QFxGridView::LeftToRight && event->key() == Qt::Key_Down)
+ || (d->flow == QFxGridView::TopToBottom && event->key() == Qt::Key_Right)) {
+ if (currentIndex() < d->model->count() - d->columns || d->wrap) {
+ d->keyPressed = true;
+ d->moveReason = QFxGridViewPrivate::Key;
+ int index = currentIndex()+d->columns;
+ setCurrentIndex(index < d->model->count() ? index : 0);
+ event->accept();
+ }
+ return;
+ } else if ((d->flow == QFxGridView::LeftToRight && event->key() == Qt::Key_Left)
+ || (d->flow == QFxGridView::TopToBottom && event->key() == Qt::Key_Up)) {
+ if (currentIndex() > 0 || d->wrap) {
+ d->keyPressed = true;
+ d->moveReason = QFxGridViewPrivate::Key;
+ int index = currentIndex() - 1;
+ setCurrentIndex(index >= 0 ? index : d->model->count()-1);
+ event->accept();
+ }
+ return;
+ } else if ((d->flow == QFxGridView::LeftToRight && event->key() == Qt::Key_Right)
+ || (d->flow == QFxGridView::TopToBottom && event->key() == Qt::Key_Down)) {
+ if (currentIndex() < d->model->count() - 1 || d->wrap) {
+ d->keyPressed = true;
+ d->moveReason = QFxGridViewPrivate::Key;
+ int index = currentIndex() + 1;
+ setCurrentIndex(index < d->model->count() ? index : 0);
+ event->accept();
+ }
+ return;
+ }
+ }
+ d->moveReason = QFxGridViewPrivate::Other;
+ QFxFlickable::keyPressEvent(event);
+}
+
+/*!
+ \reimp
+*/
+void QFxGridView::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QFxGridView);
+ d->keyPressed = false;
+ QFxFlickable::keyReleaseEvent(event);
+}
+
+/*!
+ \reimp
+*/
+void QFxGridView::componentComplete()
+{
+ Q_D(QFxGridView);
+ QFxFlickable::componentComplete();
+ d->updateGrid();
+ if (d->currentIndex < 0)
+ d->updateCurrent(0);
+ refill();
+}
+
+void QFxGridView::trackedPositionChanged()
+{
+ Q_D(QFxGridView);
+ if (!d->trackedItem)
+ return;
+ if (!isFlicking() && !d->pressed && d->moveReason == QFxGridViewPrivate::Key) {
+ if (d->trackedItem->rowPos() < d->position()) {
+ d->setPosition(d->trackedItem->rowPos());
+ } else if (d->trackedItem->endRowPos() > d->position() + d->size()) {
+ qreal pos = d->trackedItem->endRowPos() - d->size();
+ if (d->rowSize() > d->size())
+ pos = d->trackedItem->rowPos();
+ d->setPosition(pos);
+ }
+ }
+}
+
+void QFxGridView::itemsInserted(int modelIndex, int count)
+{
+ Q_D(QFxGridView);
+ if (!d->visibleItems.count() || d->model->count() <= 1) {
+ refill();
+ d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1)));
+ emit countChanged();
+ return;
+ }
+
+ int index = d->mapFromModel(modelIndex);
+ if (index == -1) {
+ int i = d->visibleItems.count() - 1;
+ while (i > 0 && d->visibleItems.at(i)->index == -1)
+ --i;
+ if (d->visibleItems.at(i)->index + 1 == modelIndex) {
+ // Special case of appending an item to the model.
+ index = d->visibleIndex + d->visibleItems.count();
+ } else {
+ if (modelIndex + count - 1 < d->visibleIndex) {
+ // Insert before visible items
+ d->visibleIndex += count;
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxGridItem *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1 && listItem != d->currentItem)
+ listItem->index += count;
+ }
+ }
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem)
+ d->currentItem->index = d->currentIndex;
+ }
+ d->layout();
+ emit countChanged();
+ return;
+ }
+ }
+
+ // At least some of the added items will be visible
+ int insertCount = count;
+ if (index < d->visibleIndex) {
+ insertCount -= d->visibleIndex - index;
+ index = d->visibleIndex;
+ modelIndex = d->visibleIndex;
+ }
+
+ index -= d->visibleIndex;
+ int to = d->buffer+d->position()+d->size()-1;
+ int colPos, rowPos;
+ if (index < d->visibleItems.count()) {
+ colPos = d->visibleItems.at(index)->colPos();
+ rowPos = d->visibleItems.at(index)->rowPos();
+ } else {
+ // appending items to visible list
+ colPos = d->visibleItems.at(index-1)->colPos() + d->colSize();
+ rowPos = d->visibleItems.at(index-1)->rowPos();
+ if (colPos > d->colSize() * (d->columns-1)) {
+ colPos = 0;
+ rowPos += d->rowSize();
+ }
+ }
+
+ QList<FxGridItem*> added;
+ int i = 0;
+ for (; i < insertCount && rowPos + d->rowSize() - 1 <= to; ++i) {
+ int mod = (modelIndex+i) % d->columns;
+ while (mod++ < d->columns && modelIndex + i < d->model->count() && i < insertCount) {
+ FxGridItem *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(index, item);
+ item->setPosition(colPos, rowPos);
+ added.append(item);
+ colPos += d->colSize();
+ if (colPos > d->colSize() * (d->columns-1)) {
+ colPos = 0;
+ rowPos += d->rowSize();
+ }
+ ++index;
+ ++i;
+ }
+ }
+
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem) {
+ d->currentItem->index = d->currentIndex;
+ d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
+ }
+ }
+ if (i < insertCount) {
+ // We didn't insert all our new items, which means anything
+ // beyond the current index is not visible - remove it.
+ while (d->visibleItems.count() > index)
+ d->releaseItem(d->visibleItems.takeLast());
+ } else {
+ // Update the indexes of the following visible items.
+ for (; index < d->visibleItems.count(); ++index) {
+ FxGridItem *listItem = d->visibleItems.at(index);
+ if (listItem != d->currentItem) {
+ if (listItem->index != -1)
+ listItem->index += count;
+ }
+ }
+ }
+ // everything is in order now - emit add() signal
+ for (int j = 0; j < added.count(); ++j)
+ added.at(j)->attached->emitAdd();
+ d->layout();
+ emit countChanged();
+}
+
+void QFxGridView::itemsRemoved(int modelIndex, int count)
+{
+ Q_D(QFxGridView);
+
+ int index = d->mapFromModel(modelIndex);
+ if (index == -1) {
+ if (modelIndex + count - 1 < d->visibleIndex) {
+ // Items removed before our visible items.
+ d->visibleIndex -= count;
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxGridItem *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1 && listItem != d->currentItem)
+ listItem->index -= count;
+ }
+ }
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ if (d->currentItem)
+ d->currentItem->index -= count;
+ } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
+ // current item has been removed.
+ if (d->currentItem) {
+ FxGridItem *item = d->currentItem;
+ d->currentItem = 0;
+ d->releaseItem(item);
+ }
+ d->currentIndex = -1;
+ d->updateCurrent(qMin(modelIndex, d->model->count()-1));
+ }
+ d->layout(true);
+ emit countChanged();
+ return;
+ }
+
+ // Remove the items from the visible list, skipping anything already marked for removal
+ QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxGridItem *item = *it;
+ if (item->index == -1 || item->index < modelIndex) {
+ // already removed, or before removed items
+ ++it;
+ } else if (item->index >= modelIndex + count) {
+ // after removed items
+ if (item != d->currentItem)
+ item->index -= count;
+ ++it;
+ } else {
+ // removed item
+ item->attached->emitRemove();
+ if (item->attached->delayRemove()) {
+ item->index = -1;
+ connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
+ ++it;
+ } else {
+ it = d->visibleItems.erase(it);
+ d->releaseItem(item);
+ }
+ }
+ }
+
+ // fix current
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ if (d->currentItem)
+ d->currentItem->index -= count;
+ } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
+ // current item has been removed.
+ if (d->currentItem && !d->currentItem->attached->delayRemove()) {
+ FxGridItem *item = d->currentItem;
+ d->currentItem = 0;
+ d->releaseItem(item);
+ }
+ d->currentItem = 0;
+ d->currentIndex = -1;
+ d->updateCurrent(qMin(modelIndex, d->model->count()-1));
+ }
+
+ // update visibleIndex
+ for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ d->visibleIndex = (*it)->index;
+ break;
+ }
+ }
+
+ if (d->visibleItems.isEmpty()) {
+ d->visibleIndex = 0;
+ d->setPosition(0);
+ refill();
+ } else {
+ // Correct the positioning of the items
+ d->layout();
+ }
+ emit countChanged();
+}
+
+void QFxGridView::destroyRemoved()
+{
+ Q_D(QFxGridView);
+ for (QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
+ it != d->visibleItems.end();) {
+ FxGridItem *listItem = *it;
+ if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
+ d->releaseItem(listItem);
+ it = d->visibleItems.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ // Correct the positioning of the items
+ d->layout();
+}
+
+void QFxGridView::refill()
+{
+ Q_D(QFxGridView);
+ d->refill(d->position(), d->position()+d->size()-1);
+}
+
+
+QObject *QFxGridView::qmlAttachedProperties(QObject *obj)
+{
+ return QFxGridViewAttached::properties(obj);
+}
+
+QML_DEFINE_TYPE(QFxGridView,GridView);
+
+QT_END_NAMESPACE
+
+#include "qfxgridview.moc"
diff --git a/src/declarative/fx/qfxgridview.h b/src/declarative/fx/qfxgridview.h
new file mode 100644
index 0000000..2bbfc40
--- /dev/null
+++ b/src/declarative/fx/qfxgridview.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXGRIDVIEW_H
+#define QFXGRIDVIEW_H
+
+#include <qfxflickable.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxVisualItemModel;
+class QFxGridViewPrivate;
+class Q_DECLARATIVE_EXPORT QFxGridView : public QFxFlickable
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFxGridView);
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel);
+ Q_CLASSINFO("DefaultProperty", "delegate");
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate);
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged);
+ Q_PROPERTY(QFxItem *current READ currentItem NOTIFY currentIndexChanged);
+ Q_PROPERTY(int count READ count NOTIFY countChanged);
+ Q_PROPERTY(QmlComponent *highlight READ highlight WRITE setHighlight);
+ Q_PROPERTY(bool autoHighlight READ autoHighlight WRITE setAutoHighlight);
+ Q_PROPERTY(Flow flow READ flow WRITE setFlow);
+ Q_PROPERTY(bool wrap READ isWrapEnabled WRITE setWrapEnabled);
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer);
+ Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellSizeChanged);
+ Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellSizeChanged);
+
+public:
+ QFxGridView(QFxItem *parent=0);
+ ~QFxGridView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ QFxItem *currentItem();
+ int count() const;
+
+ QmlComponent *highlight() const;
+ void setHighlight(QmlComponent *highlight);
+
+ bool autoHighlight() const;
+ void setAutoHighlight(bool);
+
+ Q_ENUMS(Flow);
+ enum Flow { LeftToRight, TopToBottom };
+ Flow flow() const;
+ void setFlow(Flow);
+
+ bool isWrapEnabled() const;
+ void setWrapEnabled(bool);
+
+ int cacheBuffer() const;
+ void setCacheBuffer(int);
+
+ int cellWidth() const;
+ void setCellWidth(int);
+
+ int cellHeight() const;
+ void setCellHeight(int);
+
+ static QObject *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void countChanged();
+ void currentIndexChanged();
+ void cellSizeChanged();
+
+protected:
+ virtual void viewportMoved();
+ virtual qreal minYExtent() const;
+ virtual qreal maxYExtent() const;
+ virtual qreal minXExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void componentComplete();
+
+private Q_SLOTS:
+ void trackedPositionChanged();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void destroyRemoved();
+ void sizeChange();
+
+private:
+ void refill();
+};
+
+QML_DECLARE_TYPE(QFxGridView);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/fx/qfxhighlightfilter.cpp b/src/declarative/fx/qfxhighlightfilter.cpp
new file mode 100644
index 0000000..a22ad98
--- /dev/null
+++ b/src/declarative/fx/qfxhighlightfilter.cpp
@@ -0,0 +1,319 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxhighlightfilter.h"
+#include <qfxpixmap.h>
+#include <qmlcontext.h>
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <gltexture.h>
+#include <glbasicshaders.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#include <glsave.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QFxHighlightFilterPrivate
+{
+public:
+ QFxHighlightFilterPrivate()
+ : xOffset(0), yOffset(0), tiled(false) {}
+
+ QString source;
+ QUrl url;
+ int xOffset;
+ int yOffset;
+ bool tiled;
+#if defined(QFX_RENDER_OPENGL2)
+ GLTexture tex;
+#endif
+};
+
+/*!
+ \qmlclass Highlight
+ \brief The Highlight filter adds a highlight to an item.
+ \inherits Filter
+
+ \qml
+Text {
+ id: highlighttext
+ color: "red"
+ font.size: 32
+ text: "Highlight"
+ filter: Highlight {
+ source: "pics/highlight.png"
+ xOffset: NumericAnimation {
+ running: true
+ repeat: true
+ from: 320
+ to: -320
+ duration: 2000
+ }
+ }
+}
+ \endqml
+ \image highlight.gif
+
+ Highlighting is only supported when Qt Declarative is compiled for OpenGL ES 2.0.
+ Otherwise the Highlight filter has no effect.
+*/
+
+/*!
+ \internal
+ \class QFxHighlightFilter
+ \ingroup group_effects
+ \brief The QFxHightlightFilter class allows you to add a highlight to an item.
+*/
+
+QFxHighlightFilter::QFxHighlightFilter(QObject *parent)
+: QSimpleCanvasFilter(parent), d(new QFxHighlightFilterPrivate)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ d->tex.setHorizontalWrap(GLTexture::ClampToEdge);
+ d->tex.setVerticalWrap(GLTexture::ClampToEdge);
+#endif
+}
+
+QFxHighlightFilter::~QFxHighlightFilter()
+{
+ delete d;
+ d = 0;
+}
+
+/*!
+ \qmlproperty string Highlight::source
+ This property holds the URL of the image to be used as the highlight.
+*/
+
+/*!
+ \property QFxHighlightFilter::source
+ \brief the URL of the image to be used as the highlight.
+*/
+QString QFxHighlightFilter::source() const
+{
+ return d->source;
+}
+
+void QFxHighlightFilter::imageLoaded()
+{
+ QImage img = QFxPixmap(d->url);
+#if defined(QFX_RENDER_OPENGL2)
+ if (!img.isNull())
+ d->tex.setImage(img);
+#endif
+ emit sourceChanged(d->source);
+ update();
+}
+
+void QFxHighlightFilter::setSource(const QString &f)
+{
+ if (d->source == f)
+ return;
+ if (!d->source.isEmpty())
+ QFxPixmap::cancelGet(d->url, this);
+ d->source = f;
+ d->url = qmlContext(this)->resolvedUrl(f);
+#if defined(QFX_RENDER_OPENGL2)
+ d->tex.clear();
+#endif
+ if (!f.isEmpty())
+ QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(imageLoaded()));
+ else
+ emit sourceChanged(d->source);
+}
+
+/*!
+ \qmlproperty bool Highlight::tiled
+ This property holds whether or not the highlight should be tiled.
+*/
+
+/*!
+ \property QFxHighlightFilter::tiled
+ \brief whether or not the highlight should be tiled.
+*/
+bool QFxHighlightFilter::tiled() const
+{
+ return d->tiled;
+}
+
+void QFxHighlightFilter::setTiled(bool t)
+{
+ if (t == d->tiled)
+ return;
+
+ d->tiled = t;
+
+#if defined(QFX_RENDER_OPENGL2)
+ if (d->tiled) {
+ d->tex.setHorizontalWrap(GLTexture::ClampToEdge);
+ d->tex.setVerticalWrap(GLTexture::ClampToEdge);
+ } else {
+ d->tex.setHorizontalWrap(GLTexture::Repeat);
+ d->tex.setVerticalWrap(GLTexture::Repeat);
+ }
+#endif
+
+ emit tiledChanged(d->tiled);
+}
+
+/*!
+ \qmlproperty int Highlight::xOffset
+ \qmlproperty int Highlight::yOffset
+ These properties hold the position of the highlight, relative to the item.
+*/
+
+/*!
+ \property QFxHighlightFilter::xOffset
+ \brief the x position of the highlight, relative to the item.
+*/
+int QFxHighlightFilter::xOffset() const
+{
+ return d->xOffset;
+}
+
+void QFxHighlightFilter::setXOffset(int x)
+{
+ if (x == d->xOffset)
+ return;
+
+ d->xOffset = x;
+ emit offsetChanged(d->xOffset, d->yOffset);
+#if defined(QFX_RENDER_OPENGL2)
+ update();
+#endif
+}
+
+/*!
+ \property QFxHighlightFilter::yOffset
+ \brief the y position of the highlight, relative to the item.
+*/
+int QFxHighlightFilter::yOffset() const
+{
+ return d->yOffset;
+}
+
+void QFxHighlightFilter::setYOffset(int y)
+{
+ if (y == d->yOffset)
+ return;
+
+ d->yOffset = y;
+ emit offsetChanged(d->xOffset, d->yOffset);
+#if defined(QFX_RENDER_OPENGL2)
+ update();
+#endif
+}
+
+void QFxHighlightFilter::filterGL(QSimpleCanvasItem::GLPainter &p)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ if (d->tex.isNull()) {
+ renderToScreen();
+ } else {
+ QSimpleCanvasItem *item = this->item();
+
+ QRect r = item->itemBoundingRect();
+
+ QGLFramebufferObject *fbo = renderToFBO();
+
+ float width = r.width();
+ float height = r.height();
+
+ float texWidth = width / float(fbo->width());
+ float texHeight = height / float(fbo->height());
+
+ GLfloat vert[] = { 0, height,
+ width, height,
+ 0, 0,
+ width, 0 };
+ GLfloat texVert[] = { 0, 0,
+ texWidth, 0,
+ 0, texHeight,
+ texWidth, texHeight };
+ float texXOffset = 0;
+ float texYOffset = 0;
+
+ if (xOffset())
+ texXOffset = float(xOffset()) / float(d->tex.width());
+ if (yOffset())
+ texYOffset = float(yOffset()) / float(d->tex.height());
+
+ GLfloat addTexVert[] = { texXOffset, texYOffset,
+ 1 + texXOffset, texYOffset,
+ texXOffset, 1 + texYOffset,
+ 1 + texXOffset, 1 + texYOffset };
+
+ glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, fbo->texture());
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, d->tex.texture());
+
+ DualTextureAddShader *shader = item->basicShaders()->dualTextureAdd();
+ shader->enable();
+ shader->setTransform(p.activeTransform);
+ shader->setOpacity(p.activeOpacity);
+
+ shader->setAttributeArray(DualTextureAddShader::Vertices, vert, 2);
+ shader->setAttributeArray(DualTextureAddShader::TextureCoords, texVert, 2);
+ shader->setAttributeArray(DualTextureAddShader::AddTextureCoords, addTexVert, 2);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(DualTextureAddShader::Vertices);
+ shader->disableAttributeArray(DualTextureAddShader::TextureCoords);
+ shader->disableAttributeArray(DualTextureAddShader::AddTextureCoords);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ releaseFBO(fbo);
+ }
+#else
+ Q_UNUSED(p);
+#endif
+}
+
+QML_DEFINE_TYPE(QFxHighlightFilter,Highlight);
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxhighlightfilter.h b/src/declarative/fx/qfxhighlightfilter.h
new file mode 100644
index 0000000..218f4e1
--- /dev/null
+++ b/src/declarative/fx/qfxhighlightfilter.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXHIGHLIGHTFILTER_H
+#define QFXHIGHLIGHTFILTER_H
+
+#include <qsimplecanvasfilter.h>
+#include <qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxHighlightFilterPrivate;
+class Q_DECLARATIVE_EXPORT QFxHighlightFilter : public QSimpleCanvasFilter
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(bool tiled READ tiled WRITE setTiled NOTIFY tiledChanged)
+ Q_PROPERTY(int xOffset READ xOffset WRITE setXOffset NOTIFY offsetChanged)
+ Q_PROPERTY(int yOffset READ yOffset WRITE setYOffset NOTIFY offsetChanged)
+public:
+ QFxHighlightFilter(QObject *parent=0);
+ virtual ~QFxHighlightFilter();
+
+ QString source() const;
+ void setSource(const QString &);
+
+ bool tiled() const;
+ void setTiled(bool);
+
+ int xOffset() const;
+ void setXOffset(int);
+ int yOffset() const;
+ void setYOffset(int);
+
+Q_SIGNALS:
+ void sourceChanged(const QString &);
+ void offsetChanged(int x, int y);
+ void tiledChanged(bool);
+
+private Q_SLOTS:
+ void imageLoaded();
+
+protected:
+ virtual void filterGL(QSimpleCanvasItem::GLPainter &p);
+
+private:
+ QFxHighlightFilterPrivate *d;
+};
+QML_DECLARE_TYPE(QFxHighlightFilter);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXHIGHLIGHTFILTER_H
diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp
new file mode 100644
index 0000000..dfd6915
--- /dev/null
+++ b/src/declarative/fx/qfximage.cpp
@@ -0,0 +1,1009 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfximage.h"
+#include "qfximage_p.h"
+#include <qfxperf.h>
+#if defined(QFX_RENDER_OPENGL)
+#include <glsave.h>
+#endif
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QFile>
+#include <QtDeclarative/qmlengine.h>
+
+QT_BEGIN_NAMESPACE
+
+
+QML_DEFINE_TYPE(QFxImage,Image);
+
+/*!
+ \qmlclass Image QFxImage
+ \brief The Image element allows you to add bitmaps to a scene.
+ \inherits Item
+
+ The Image element supports untransformed, stretched, grid-scaled and tiled images.
+ For an explanation of grid-scaling see the scaleGrid property description
+ or the QFxScaleGrid class description.
+
+ Examples:
+ \table
+ \row
+ \o \image declarative-qtlogo1.png
+ \o Untransformed
+ \qml
+ Image { source: "pics/qtlogo.png" }
+ \endqml
+ \row
+ \o \image declarative-qtlogo2.png
+ \o Stretched
+ \qml
+ Image { width: 160; height: 160; source: "pics/qtlogo.png" }
+ \endqml
+ \row
+ \o \image declarative-qtlogo4.png
+ \o Grid-scaled
+ \qml
+ Image { scaleGrid.left: 20; scaleGrid.right: 10
+ scaleGrid.top: 14; scaleGrid.bottom: 14
+ width: 160; height: 160; source: "pics/qtlogo.png" }
+ \endqml
+ \row
+ \o \image declarative-qtlogo3.png
+ \o Tiled
+ \qml
+ Image { tile: true; width: 160; height: 160; source: "pics/qtlogo.png" }
+ \endqml
+ \endtable
+ */
+
+/*!
+ \internal
+ \class QFxImage Image
+ \brief The QFxImage class provides an image item that you can add to a QFxView.
+
+ \ingroup group_coreitems
+
+ Example:
+ \qml
+ Image { source: "pics/star.png" }
+ \endqml
+
+ A QFxImage object can be instantiated in Qml using the tag \l Image.
+*/
+
+QFxImage::QFxImage(QFxItem *parent)
+ : QFxItem(*(new QFxImagePrivate), parent)
+{
+ setOptions(SimpleItem | HasContents, true);
+}
+
+QFxImage::QFxImage(QFxImagePrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ setOptions(SimpleItem | HasContents, true);
+}
+
+QFxImage::~QFxImage()
+{
+ Q_D(const QFxImage);
+ if (d->sciReply)
+ d->sciReply->deleteLater();
+}
+
+/*!
+ \property QFxImage::pixmap
+ \brief the image displayed in this item.
+
+ This property contains the image currently being displayed by this item,
+ which may be an empty pixmap if nothing is currently displayed. If this
+ property is set, the source property will be unset. This property is intended
+ to be used only in C++, not in QML.
+*/
+QPixmap QFxImage::pixmap() const
+{
+ Q_D(const QFxImage);
+ return d->_pix.pixmap();
+}
+
+void QFxImage::setPixmap(const QPixmap &pix)
+{
+ Q_D(QFxImage);
+ d->url = QUrl();
+ d->_pix.setPixmap(pix);
+ d->_opaque=false;
+ d->_pix.setOpaque(false);
+
+ setImplicitWidth(d->_pix.width());
+ setImplicitHeight(d->_pix.height());
+
+#if defined(QFX_RENDER_OPENGL)
+ d->_texDirty = true;
+ d->_tex.clear();
+#endif
+ update();
+}
+
+/*!
+ \qmlproperty int Image::scaleGrid.left
+ \qmlproperty int Image::scaleGrid.right
+ \qmlproperty int Image::scaleGrid.top
+ \qmlproperty int Image::scaleGrid.bottom
+
+ \target ImagexmlpropertiesscaleGrid
+
+ A scale grid uses 4 grid lines (2 horizontal and 2 vertical) to break an image into 9 sections, as shown below:
+
+ \image declarative-scalegrid.png
+
+ When the image is scaled:
+ \list
+ \i the corners (sections 1, 3, 7, and 9) are not scaled at all
+ \i the middle (section 5) is scaled both horizontally and vertically
+ \i sections 2 and 8 are scaled horizontally
+ \i sections 4 and 6 are scaled vertically
+ \endlist
+
+ Each scale grid property (left, right, top, and bottom) specifies an offset from the respective side. For example, \c scaleGrid.bottom="10" sets the bottom scale grid line 10 pixels up from the bottom of the image.
+
+ A scale grid can also be specified using a
+ \l {Image::source}{.sci file}.
+*/
+QFxScaleGrid *QFxImage::scaleGrid()
+{
+ Q_D(QFxImage);
+ return d->scaleGrid();
+}
+
+/*!
+ \qmlproperty bool Image::tile
+
+ Set this property to enable image tiling. Normally the Image element scales the
+ bitmap file to its size. If tiling is enabled, the bitmap is repeated as a set
+ of unscaled tiles, clipped to the size of the Image.
+
+ \qml
+ Item {
+ Image { source: "tile.png" }
+ Image { x: 80; width: 100; height: 100; source: "tile.png" }
+ Image { x: 190; width: 100; height: 100; tile: true; source: "tile.png" }
+ }
+ \endqml
+ \image declarative-image_tile.png
+
+ If both tiling and the scaleGrid are set, tiling takes precedence.
+*/
+bool QFxImage::isTiled() const
+{
+ Q_D(const QFxImage);
+ return d->_tiled;
+}
+
+void QFxImage::setTiled(bool tile)
+{
+ Q_D(QFxImage);
+ d->_tiled = tile;
+}
+
+/*!
+ \qmlproperty bool Image::opaque
+
+ Set this property if you know that the image is opaque to give your
+ application a significant performance boost.
+
+ \note
+ This is a performance hint to Qt Declarative. Unfortunately whether or not an image
+ is opaque is not automatically detected. Setting this property to true when
+ the image is not opaque will lead to drawing artifacts. However, leaving it as
+ false will always work correctly - although possibly not at maximum performance.
+ */
+
+/*!
+ \property QFxImage::opaque
+ \brief whether the image is opaque (non-transparent).
+
+ This property is provided purely for the purpose of optimization. An opaque
+ image can be optimized more than a non-opaque one.
+*/
+bool QFxImage::isOpaque() const
+{
+ Q_D(const QFxImage);
+ return d->_opaque;
+}
+
+void QFxImage::setOpaque(bool o)
+{
+ Q_D(QFxImage);
+ if (o == d->_opaque)
+ return;
+ d->_opaque = o;
+ d->_pix.setOpaque(o);
+ update();
+}
+
+void QFxImage::componentComplete()
+{
+ QFxItem::componentComplete();
+}
+
+/*!
+ \property QFxImage::scaleGrid
+ \brief the 3x3 grid used to scale an image, excluding the corners.
+*/
+
+/*!
+ \qmlproperty bool Image::smooth
+
+ Set this property if you want the image to be smoothly filtered when scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the Image is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the image is stationary on
+ the screen. A common pattern when animating an image is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+ */
+
+/*!
+ \property QFxImage::smooth
+ \brief whether the image is smoothly transformed.
+
+ This property is provided purely for the purpose of optimization. Turning
+ smooth transforms off is faster, but looks worse; turning smooth
+ transformations on is slower, but looks better.
+
+ By default smooth transformations are off.
+*/
+bool QFxImage::smoothTransform() const
+{
+ Q_D(const QFxImage);
+ return d->_smooth;
+}
+
+void QFxImage::setSmoothTransform(bool s)
+{
+ Q_D(QFxImage);
+ if (d->_smooth == s)
+ return;
+ d->_smooth = s;
+ update();
+}
+
+void QFxImage::dump(int depth)
+{
+ Q_D(QFxImage);
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << "URL:" << d->url;
+ QFxItem::dump(depth);
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+void QFxImage::paintContents(QPainter &p)
+{
+ Q_D(QFxImage);
+ if (d->_pix.isNull())
+ return;
+
+ if (d->_smooth) {
+ p.save();
+ p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->_smooth);
+ }
+
+ QSimpleCanvasConfig::Image pix = d->_pix;
+
+ if (d->_tiled) {
+ p.save();
+ p.setClipRect(0, 0, width(), height(), Qt::IntersectClip);
+ QRect me = QRect(0, 0, width(), height());
+
+ int pw = d->_pix.width();
+ int ph = d->_pix.height();
+ int yy = 0;
+
+ while(yy < height()) {
+ int xx = 0;
+ while(xx < width()) {
+ p.drawImage(xx, yy, d->_pix);
+ xx += pw;
+ }
+ yy += ph;
+ }
+
+ p.restore();
+ } else if (!d->_scaleGrid || d->_scaleGrid->isNull()) {
+ if (width() != pix.width() || height() != pix.height()) {
+ QTransform scale;
+ scale.scale(width() / qreal(pix.width()),
+ height() / qreal(pix.height()));
+ QTransform old = p.transform();
+ p.setWorldTransform(scale * old);
+ p.drawImage(0, 0, pix);
+ p.setWorldTransform(old);
+ } else {
+ p.drawImage(0, 0, pix);
+ }
+ } else {
+ const int sgl = d->_scaleGrid->left();
+ const int sgr = d->_scaleGrid->right();
+ const int sgt = d->_scaleGrid->top();
+ const int sgb = d->_scaleGrid->bottom();
+ const int xSide = sgl + sgr;
+ const int ySide = sgt + sgb;
+
+ // Upper left
+ if (sgt && sgl)
+ p.drawImage(QRect(0, 0, sgl, sgt), pix, QRect(0, 0, sgl, sgt));
+ // Upper middle
+ if (pix.width() - xSide && sgt)
+ p.drawImage(QRect(sgl, 0, width() - xSide, sgt), pix,
+ QRect(sgl, 0, pix.width() - xSide, sgt));
+ // Upper right
+ if (sgt && pix.width() - sgr)
+ p.drawImage(QPoint(width()-sgr, 0), pix,
+ QRect(pix.width()-sgr, 0, sgr, sgt));
+ // Middle left
+ if (sgl && pix.height() - ySide)
+ p.drawImage(QRect(0, sgt, sgl, height() - ySide), pix,
+ QRect(0, sgt, sgl, pix.height() - ySide));
+
+ // Middle
+ if (pix.width() - xSide && pix.height() - ySide)
+ p.drawImage(QRect(sgl, sgt, width() - xSide, height() - ySide),
+ pix,
+ QRect(sgl, sgt, pix.width() - xSide, pix.height() - ySide));
+ // Middle right
+ if (sgr && pix.height() - ySide)
+ p.drawImage(QRect(width()-sgr, sgt, sgr, height() - ySide), pix,
+ QRect(pix.width()-sgr, sgt, sgr, pix.height() - ySide));
+ // Lower left
+ if (sgl && sgr)
+ p.drawImage(QPoint(0, height() - sgb), pix,
+ QRect(0, pix.height() - sgb, sgl, sgb));
+ // Lower Middle
+ if (pix.width() - xSide && sgb)
+ p.drawImage(QRect(sgl, height() - sgb, width() - xSide, sgb), pix,
+ QRect(sgl, pix.height() - sgb, pix.width() - xSide, sgb));
+ // Lower Right
+ if (sgr && sgb)
+ p.drawImage(QPoint(width()-sgr, height() - sgb), pix,
+ QRect(pix.width()-sgr, pix.height() - sgb, sgr, sgb));
+ }
+
+ if (d->_smooth) {
+ p.restore();
+ }
+}
+#elif defined(QFX_RENDER_OPENGL)
+uint QFxImage::glSimpleItemData(float *vertices, float *texVertices,
+ GLTexture **texture, uint count)
+{
+ Q_D(QFxImage);
+
+ if (d->_pix.isNull() || (d->_scaleGrid && !d->_scaleGrid->isNull()))
+ return 0;
+
+ if (count < 8)
+ return 8;
+
+ d->checkDirty();
+
+ float widthV = width();
+ float heightV = height();
+
+ vertices[0] = 0; vertices[1] = heightV;
+ vertices[2] = widthV; vertices[3] = heightV;
+ vertices[4] = 0; vertices[5] = 0;
+ vertices[6] = widthV; vertices[7] = 0;
+
+ *texture = &d->_tex;
+
+ if (d->_tiled) {
+ float tileWidth = widthV / d->_pix.width();
+ float tileHeight = heightV / d->_pix.height();
+ texVertices[0] = 0; texVertices[1] = 0;
+ texVertices[2] = tileWidth; texVertices[3] = 0;
+ texVertices[4] = 0; texVertices[5] = tileHeight;
+ texVertices[6] = tileWidth; texVertices[7] = tileHeight;
+ } else {
+ texVertices[0] = 0; texVertices[1] = 0;
+ texVertices[2] = 1; texVertices[3] = 0;
+ texVertices[4] = 0; texVertices[5] = 1;
+ texVertices[6] = 1; texVertices[7] = 1;
+ }
+
+ return 8;
+}
+
+void QFxImagePrivate::checkDirty()
+{
+ if (_texDirty && !_pix.isNull()) {
+ _tex.setImage(_pix);
+ _tex.setHorizontalWrap(GLTexture::Repeat);
+ _tex.setVerticalWrap(GLTexture::Repeat);
+ }
+ _texDirty = false;
+}
+
+#if defined(QFX_RENDER_OPENGL2)
+void QFxImage::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxImage);
+ if (d->_pix.isNull())
+ return;
+
+ QGLShaderProgram *shader = p.useTextureShader();
+
+ bool restoreBlend = false;
+ if (isOpaque() && p.activeOpacity == 1) {
+ glDisable(GL_BLEND);
+ restoreBlend = true;
+ }
+
+ if (d->_tiled || (!d->_scaleGrid || d->_scaleGrid->isNull())) {
+
+ GLfloat vertices[8];
+ GLfloat texVertices[8];
+ GLTexture *tex = 0;
+
+ QFxImage::glSimpleItemData(vertices, texVertices, &tex, 8);
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2);
+
+ glBindTexture(GL_TEXTURE_2D, tex->texture());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+
+ } else {
+ d->checkDirty();
+
+ float imgWidth = d->_pix.width();
+ float imgHeight = d->_pix.height();
+ if (!imgWidth || !imgHeight) {
+ if (restoreBlend)
+ glEnable(GL_BLEND);
+ return;
+ }
+
+ float widthV = width();
+ float heightV = height();
+
+ float texleft = 0;
+ float texright = 1;
+ float textop = 1;
+ float texbottom = 0;
+ float imgleft = 0;
+ float imgright = widthV;
+ float imgtop = 0;
+ float imgbottom = heightV;
+
+ const int sgl = d->_scaleGrid->left();
+ const int sgr = d->_scaleGrid->right();
+ const int sgt = d->_scaleGrid->top();
+ const int sgb = d->_scaleGrid->bottom();
+
+ if (sgl) {
+ texleft = float(sgl) / imgWidth;
+ imgleft = sgl;
+ }
+ if (sgr) {
+ texright = 1. - float(sgr) / imgWidth;
+ imgright = widthV - sgr;
+ }
+ if (sgt) {
+ textop = 1. - float(sgb) / imgHeight;
+ imgtop = sgt;
+ }
+ if (sgb) {
+ texbottom = float(sgt) / imgHeight;
+ imgbottom = heightV - sgb;
+ }
+
+ float vert1[] = { 0, 0,
+ 0, imgtop,
+ imgleft, 0,
+ imgleft, imgtop,
+ imgright, 0,
+ imgright, imgtop,
+ widthV, 0,
+ widthV, imgtop };
+ float tex1[] = { 0, 1,
+ 0, textop,
+ texleft, 1,
+ texleft, textop,
+ texright, 1,
+ texright, textop,
+ 1, 1,
+ 1, textop };
+ float vert2[] = { 0, imgtop,
+ 0, imgbottom,
+ imgleft, imgtop,
+ imgleft, imgbottom,
+ imgright, imgtop,
+ imgright, imgbottom,
+ widthV, imgtop,
+ widthV, imgbottom };
+ float tex2[] = { 0, textop,
+ 0, texbottom,
+ texleft, textop,
+ texleft, texbottom,
+ texright, textop,
+ texright, texbottom,
+ 1, textop,
+ 1, texbottom };
+ float vert3[] = { 0, imgbottom,
+ 0, heightV,
+ imgleft, imgbottom,
+ imgleft, heightV,
+ imgright, imgbottom,
+ imgright, heightV,
+ widthV, imgbottom,
+ widthV, heightV };
+ float tex3[] = { 0, texbottom,
+ 0, 0,
+ texleft, texbottom,
+ texleft, 0,
+ texright, texbottom,
+ texright, 0,
+ 1, texbottom,
+ 1, 0 };
+
+ glBindTexture(GL_TEXTURE_2D, d->_tex.texture());
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert2, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, tex2, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert3, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, tex3, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+ }
+
+ if (restoreBlend)
+ glEnable(GL_BLEND);
+}
+#elif defined(QFX_RENDER_OPENGL1)
+void QFxImage::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxImage);
+ if (d->_pix.isNull())
+ return;
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(p.activeTransform.data());
+
+ bool restoreBlend = false;
+ if (isOpaque() && p.activeOpacity == 1) {
+ glDisable(GL_BLEND);
+ restoreBlend = true;
+ }
+
+ glEnable(GL_TEXTURE_2D);
+ if (p.activeOpacity == 1.) {
+ GLint i = GL_REPLACE;
+ glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i);
+ } else {
+ GLint i = GL_MODULATE;
+ glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i);
+ glColor4f(1, 1, 1, p.activeOpacity);
+ }
+
+ if (d->_tiled || !d->_scaleGrid || d->_scaleGrid->isNull()) {
+
+ GLfloat vertices[8];
+ GLfloat texVertices[8];
+ GLTexture *tex = 0;
+
+ QFxImage::glSimpleItemData(vertices, texVertices, &tex, 8);
+
+ glBindTexture(GL_TEXTURE_2D, tex->texture());
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glTexCoordPointer(2, GL_FLOAT, 0, texVertices);
+
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D);
+
+ } else {
+ d->checkDirty();
+
+ float imgWidth = d->_pix.width();
+ float imgHeight = d->_pix.height();
+ if (!imgWidth || !imgHeight) {
+ if (restoreBlend)
+ glEnable(GL_BLEND);
+ return;
+ }
+
+ float widthV = width();
+ float heightV = height();
+
+ float texleft = 0;
+ float texright = 1;
+ float textop = 1;
+ float texbottom = 0;
+ float imgleft = 0;
+ float imgright = widthV;
+ float imgtop = 0;
+ float imgbottom = heightV;
+
+ const int sgl = d->_scaleGrid->left();
+ const int sgr = d->_scaleGrid->right();
+ const int sgt = d->_scaleGrid->top();
+ const int sgb = d->_scaleGrid->bottom();
+
+ if (sgl) {
+ texleft = float(sgl) / imgWidth;
+ imgleft = sgl;
+ }
+ if (sgr) {
+ texright = 1. - float(sgr) / imgWidth;
+ imgright = widthV - sgr;
+ }
+ if (sgt) {
+ textop = 1. - float(sgb) / imgHeight;
+ imgtop = sgt;
+ }
+ if (sgb) {
+ texbottom = float(sgt) / imgHeight;
+ imgbottom = heightV - sgb;
+ }
+
+ float vert1[] = { 0, 0,
+ 0, imgtop,
+ imgleft, 0,
+ imgleft, imgtop,
+ imgright, 0,
+ imgright, imgtop,
+ widthV, 0,
+ widthV, imgtop };
+ float tex1[] = { 0, 1,
+ 0, textop,
+ texleft, 1,
+ texleft, textop,
+ texright, 1,
+ texright, textop,
+ 1, 1,
+ 1, textop };
+ float vert2[] = { 0, imgtop,
+ 0, imgbottom,
+ imgleft, imgtop,
+ imgleft, imgbottom,
+ imgright, imgtop,
+ imgright, imgbottom,
+ widthV, imgtop,
+ widthV, imgbottom };
+ float tex2[] = { 0, textop,
+ 0, texbottom,
+ texleft, textop,
+ texleft, texbottom,
+ texright, textop,
+ texright, texbottom,
+ 1, textop,
+ 1, texbottom };
+ float vert3[] = { 0, imgbottom,
+ 0, heightV,
+ imgleft, imgbottom,
+ imgleft, heightV,
+ imgright, imgbottom,
+ imgright, heightV,
+ widthV, imgbottom,
+ widthV, heightV };
+ float tex3[] = { 0, texbottom,
+ 0, 0,
+ texleft, texbottom,
+ texleft, 0,
+ texright, texbottom,
+ texright, 0,
+ 1, texbottom,
+ 1, 0 };
+
+ glBindTexture(GL_TEXTURE_2D, d->_tex.texture());
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, 0, vert1);
+ glTexCoordPointer(2, GL_FLOAT, 0, tex1);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+ glVertexPointer(2, GL_FLOAT, 0, vert2);
+ glTexCoordPointer(2, GL_FLOAT, 0, tex2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+ glVertexPointer(2, GL_FLOAT, 0, vert3);
+ glTexCoordPointer(2, GL_FLOAT, 0, tex3);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D);
+ }
+
+ if (restoreBlend)
+ glEnable(GL_BLEND);
+}
+#endif
+
+#endif
+
+QString QFxImage::propertyInfo() const
+{
+ Q_D(const QFxImage);
+ return d->url.toString();
+}
+
+/*!
+ \qmlproperty enum Image::status
+
+ This property holds the status of image loading. It can be one of:
+ \list
+ \o Idle - no image has been set, or the image has been loaded
+ \o Loading - the images is currently being loaded
+ \o Error - an error occurred while loading the image
+ \endlist
+
+ \sa progress
+*/
+
+QFxImage::Status QFxImage::status() const
+{
+ Q_D(const QFxImage);
+ return d->status;
+}
+
+/*!
+ \qmlproperty real Image::progress
+
+ This property holds the progress of image loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+
+qreal QFxImage::progress() const
+{
+ Q_D(const QFxImage);
+ return d->progress;
+}
+
+/*!
+ \qmlproperty string Image::source
+
+ Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt.
+
+ It can also handle .sci files, which are a Qml-specific format. A .sci file uses a simple text-based format that specifies
+ \list
+ \i the grid lines describing a \l {Image::scaleGrid.left}{scale grid}.
+ \i an image file.
+ \endlist
+
+ The following .sci file sets grid line offsets of 10 on each side for the image \c picture.png:
+ \code
+ gridLeft: 10
+ gridTop: 10
+ gridBottom: 10
+ gridRight: 10
+ imageFile: picture.png
+ \endcode
+
+ The URL may be absolute, or relative to the URL of the component.
+*/
+
+/*!
+ \property QFxImage::source
+ \brief the url of the image to be displayed in this item.
+
+ The content specified can be of any image type loadable by QImage. Alternatively,
+ you can specify an sci format file, which specifies both an image and it's scale grid.
+*/
+QString QFxImage::source() const
+{
+ Q_D(const QFxImage);
+ return d->source;
+}
+
+void QFxImage::setSource(const QString &url)
+{
+ Q_D(QFxImage);
+ if (url == d->source)
+ return;
+
+ if (d->sciReply) {
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ }
+
+ if (!d->url.isEmpty())
+ QFxPixmap::cancelGet(d->url, this);
+ if (!d->sciurl.isEmpty())
+ QFxPixmap::cancelGet(d->sciurl, this);
+
+ d->source = url;
+ d->url = qmlContext(this)->resolvedUrl(url);
+ d->sciurl = QUrl();
+ if (d->progress != 0.0) {
+ d->progress = 0.0;
+ emit progressChanged(d->progress);
+ }
+
+ if (url.isEmpty()) {
+ setPixmap(QPixmap());
+ d->status = Idle;
+ d->progress = 1.0;
+ setImplicitWidth(0);
+ setImplicitHeight(0);
+#if defined(QFX_RENDER_OPENGL)
+ d->_texDirty = true;
+ d->_tex.clear();
+#endif
+ emit statusChanged(d->status);
+ emit sourceChanged(d->source);
+ emit progressChanged(1.0);
+ update();
+ } else {
+ d->status = Loading;
+ if (d->url.path().endsWith(QLatin1String(".sci"))) {
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ if (d->url.scheme() == QLatin1String("file")) {
+ QFile file(d->url.toLocalFile());
+ file.open(QIODevice::ReadOnly);
+ setGridScaledImage(QFxGridScaledImage(&file));
+ } else
+#endif
+ {
+ QNetworkRequest req(d->url);
+ req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+ d->sciReply = qmlEngine(this)->networkAccessManager()->get(req);
+ QObject::connect(d->sciReply, SIGNAL(finished()),
+ this, SLOT(sciRequestFinished()));
+ }
+ } else {
+ d->reply = QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(requestFinished()));
+ if (d->reply) {
+ connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ } else {
+ d->progress = 1.0;
+ emit progressChanged(d->progress);
+ }
+ }
+ }
+
+ emit statusChanged(d->status);
+}
+
+void QFxImage::requestFinished()
+{
+ Q_D(QFxImage);
+ if (d->url.path().endsWith(QLatin1String(".sci"))) {
+ d->_pix = QFxPixmap(d->sciurl);
+ } else {
+ if (d->reply) {
+ disconnect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ if (d->reply->error() != QNetworkReply::NoError)
+ d->status = Error;
+ }
+ d->_pix = QFxPixmap(d->url);
+ d->_pix.setOpaque(d->_opaque);
+ setOptions(QFxImage::SimpleItem, true);
+ }
+ setImplicitWidth(d->_pix.width());
+ setImplicitHeight(d->_pix.height());
+
+ if (d->status == Loading)
+ d->status = Idle;
+ d->progress = 1.0;
+#if defined(QFX_RENDER_OPENGL)
+ d->_texDirty = true;
+ d->_tex.clear();
+#endif
+ emit statusChanged(d->status);
+ emit sourceChanged(d->source);
+ emit progressChanged(1.0);
+ update();
+}
+
+void QFxImage::sciRequestFinished()
+{
+ Q_D(QFxImage);
+ if (d->sciReply->error() != QNetworkReply::NoError) {
+ d->status = Error;
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ emit statusChanged(d->status);
+ } else {
+ QFxGridScaledImage sci(d->sciReply);
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ setGridScaledImage(sci);
+ }
+}
+
+void QFxImage::requestProgress(qint64 received, qint64 total)
+{
+ Q_D(QFxImage);
+ if (d->status == Loading && total > 0) {
+ d->progress = qreal(received)/total;
+ emit progressChanged(d->progress);
+ }
+}
+
+void QFxImage::setGridScaledImage(const QFxGridScaledImage& sci)
+{
+ Q_D(QFxImage);
+ if (!sci.isValid()) {
+ d->status = Error;
+ emit statusChanged(d->status);
+ } else {
+ d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl()));
+ d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, this, SLOT(requestFinished()));
+ if (d->reply) {
+ connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ } else {
+ d->progress = 1.0;
+ emit progressChanged(d->progress);
+ }
+ QFxScaleGrid *sg = scaleGrid();
+ sg->setTop(sci.gridTop());
+ sg->setBottom(sci.gridBottom());
+ sg->setLeft(sci.gridLeft());
+ sg->setRight(sci.gridRight());
+ setOptions(QFxImage::SimpleItem, false);
+ }
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfximage.h b/src/declarative/fx/qfximage.h
new file mode 100644
index 0000000..dc13a97
--- /dev/null
+++ b/src/declarative/fx/qfximage.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXIMAGE_H
+#define QFXIMAGE_H
+
+#include <qfxitem.h>
+#include <QtNetwork/qnetworkreply.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxImagePrivate;
+class Q_DECLARATIVE_EXPORT QFxImage : public QFxItem
+{
+ Q_OBJECT
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+
+ Q_PROPERTY(QFxScaleGrid *scaleGrid READ scaleGrid)
+ Q_PROPERTY(bool tile READ isTiled WRITE setTiled)
+ Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap DESIGNABLE false)
+ Q_PROPERTY(bool opaque READ isOpaque WRITE setOpaque)
+ Q_PROPERTY(bool smooth READ smoothTransform WRITE setSmoothTransform)
+public:
+ QFxImage(QFxItem *parent=0);
+ ~QFxImage();
+
+ QFxScaleGrid *scaleGrid();
+
+ bool isTiled() const;
+ void setTiled(bool tile);
+
+ QPixmap pixmap() const;
+ void setPixmap(const QPixmap &);
+
+ bool isOpaque() const;
+ void setOpaque(bool);
+
+ bool smoothTransform() const;
+ void setSmoothTransform(bool);
+
+ enum Status { Idle, Loading, Error };
+ Status status() const;
+ qreal progress() const;
+
+ QString source() const;
+ virtual void setSource(const QString &url);
+
+ virtual void dump(int depth);
+ virtual QString propertyInfo() const;
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &painter);
+#elif defined(QFX_RENDER_OPENGL)
+ void paintGLContents(GLPainter &);
+ uint glSimpleItemData(float *vertices, float *texVertices,
+ GLTexture **texture, uint count);
+#endif
+
+Q_SIGNALS:
+ void sourceChanged(const QString &);
+ void statusChanged(Status);
+ void progressChanged(qreal progress);
+
+protected:
+ QFxImage(QFxImagePrivate &dd, QFxItem *parent);
+ virtual void componentComplete();
+
+private Q_SLOTS:
+ void requestFinished();
+ void sciRequestFinished();
+ void requestProgress(qint64,qint64);
+
+private:
+ Q_DISABLE_COPY(QFxImage)
+ Q_DECLARE_PRIVATE(QFxImage)
+ void setGridScaledImage(const QFxGridScaledImage& sci);
+};
+QML_DECLARE_TYPE(QFxImage);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXIMAGE_H
diff --git a/src/declarative/fx/qfximage_p.h b/src/declarative/fx/qfximage_p.h
new file mode 100644
index 0000000..8227ce4
--- /dev/null
+++ b/src/declarative/fx/qfximage_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXIMAGE_P_H
+#define QFXIMAGE_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 "qfxitem_p.h"
+
+#if defined(QFX_RENDER_OPENGL)
+#include "gltexture.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QSvgRenderer;
+class QWebPage;
+class QNetworkReply;
+class QIODevice;
+
+class QFxImagePrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxImage)
+
+public:
+ QFxImagePrivate()
+ : _scaleGrid(0), _tiled(false), _smooth(false), _opaque(false),
+#if defined(QFX_RENDER_OPENGL)
+ _texDirty(true),
+#endif
+ status(QFxImage::Idle), sciReply(0), progress(0.0)
+ {
+ }
+
+ ~QFxImagePrivate()
+ {
+ delete _scaleGrid;
+ }
+
+ void setContent(QIODevice* dev, const QString &url);
+
+ QFxScaleGrid *scaleGrid()
+ {
+ if (!_scaleGrid)
+ _scaleGrid = new QFxScaleGrid;
+ return _scaleGrid;
+ }
+
+ QFxScaleGrid *_scaleGrid;
+ QFxPixmap _pix;
+ bool _tiled : 1;
+ bool _smooth : 1;
+ bool _opaque : 1;
+#if defined(QFX_RENDER_OPENGL)
+ void checkDirty();
+ bool _texDirty;
+ GLTexture _tex;
+#endif
+
+ QFxImage::Status status;
+ QString source;
+ QUrl url;
+ QUrl sciurl;
+ QNetworkReply *sciReply;
+ QPointer<QNetworkReply> reply;
+ qreal progress;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFXIMAGE_P_H
diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp
new file mode 100644
index 0000000..b737615
--- /dev/null
+++ b/src/declarative/fx/qfxitem.cpp
@@ -0,0 +1,2154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include <QPen>
+#include <QFile>
+#include <QEvent>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QGraphicsSceneMouseEvent>
+#include <QtScript/qscriptengine.h>
+#include <qfxperf.h>
+
+#include "qmlengine.h"
+#include "qmlstate.h"
+#include "qlistmodelinterface.h"
+
+#include "qfxtransform.h"
+#include "qfxscalegrid.h"
+#include "qfxview.h"
+#include "qmlstategroup.h"
+
+#include "qfxitem_p.h"
+#include "qfxitem.h"
+#include "qfxevents_p.h"
+#include <qsimplecanvasfilter.h>
+#include <qmlcomponent.h>
+
+
+QT_BEGIN_NAMESPACE
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
+
+QML_DEFINE_NOCREATE_TYPE(QFxContents);
+QML_DEFINE_TYPE(QFxItem,Item);
+QML_DEFINE_NOCREATE_TYPE(QSimpleCanvasFilter);
+
+/*!
+ \group group_animation
+ \title Animation
+*/
+
+/*!
+ \group group_coreitems
+ \title Basic Items
+*/
+
+/*!
+ \group group_effects
+ \title Effects
+*/
+
+/*!
+ \group group_layouts
+ \title Layouts
+*/
+
+/*!
+ \group group_states
+ \title States and Transitions
+*/
+
+/*!
+ \group group_utility
+ \title Utility
+*/
+
+/*!
+ \group group_views
+ \title Views
+*/
+
+/*!
+ \group group_widgets
+ \title Widgets
+*/
+
+/*!
+ \internal
+ \class QFxContents
+ \ingroup group_utility
+ \brief The QFxContents class gives access to the height and width of an item's contents.
+
+*/
+
+QFxContents::QFxContents() : _height(0), _width(0)
+{
+}
+
+/*!
+ \property QFxContents::height
+ \brief The height of the contents.
+*/
+int QFxContents::height() const
+{
+ return _height;
+}
+
+/*!
+ \property QFxContents::width
+ \brief The width of the contents.
+*/
+int QFxContents::width() const
+{
+ return _width;
+}
+
+//TODO: optimization: only check sender(), if there is one
+void QFxContents::calcHeight()
+{
+ int oldheight = _height;
+
+ int top = INT_MAX;
+ int bottom = 0;
+
+ const QList<QSimpleCanvasItem *> &children = _item->QSimpleCanvasItem::children();
+ for (int i = 0; i < children.count(); ++i) {
+ const QSimpleCanvasItem *child = children.at(i);
+ int y = int(child->y());
+ if (y + child->height() > bottom)
+ bottom = y + child->height();
+ if (y < top)
+ top = y;
+ }
+ _height = bottom - top;
+
+ if (_height != oldheight)
+ emit heightChanged();
+}
+
+//TODO: optimization: only check sender(), if there is one
+void QFxContents::calcWidth()
+{
+ int oldwidth = _width;
+
+ int left = INT_MAX;
+ int right = 0;
+ const QList<QSimpleCanvasItem *> &children = _item->QSimpleCanvasItem::children();
+ for (int i = 0; i < children.count(); ++i) {
+ const QSimpleCanvasItem *child = children.at(i);
+ int x = int(child->x());
+ if (x + child->width() > right)
+ right = x + child->width();
+ if (x < left)
+ left = x;
+ }
+ _width = right - left;
+
+ if (_width != oldwidth)
+ emit widthChanged();
+}
+
+void QFxContents::setItem(QFxItem *item)
+{
+ _item = item;
+
+ const QList<QSimpleCanvasItem *> &children = _item->QSimpleCanvasItem::children();
+ for (int i = 0; i < children.count(); ++i) {
+ const QSimpleCanvasItem *child = children.at(i);
+ connect(child, SIGNAL(bottomChanged()), this, SLOT(calcHeight()));
+ connect(child, SIGNAL(rightChanged()), this, SLOT(calcWidth()));
+ }
+
+ calcHeight();
+ calcWidth();
+}
+
+/*!
+ \qmlclass Item QFxItem
+ \brief The Item is the most basic of all visual items in QML.
+ */
+
+/*!
+ \class QFxItem Item
+ \brief The QFxItem class is a generic QFxView item. It is the base class for all other view items.
+
+ \qmltext
+ All visual items in Qt Declarative inherit from QFxItem. Although QFxItem
+ has no visual appearance, it defines all the properties that are
+ common across visual items - like the x and y position, and the
+ width and height.
+
+ QFxItem is also useful for grouping items together.
+
+ \qml
+ Item {
+ Image {
+ file: "tile.png"
+ }
+ Image {
+ x: 80
+ width: 100
+ height: 100
+ file: "tile.png"
+ }
+ Image {
+ x: 190
+ width: 100
+ height: 100
+ tile: true
+ file: "tile.png"
+ }
+ }
+ \endqml
+ \endqmltext
+
+ \ingroup group_coreitems
+*/
+
+/*!
+ \property QFxItem::activeFocus
+ This property indicates whether the item has the active focus.
+ */
+
+/*!
+ \fn void QFxItem::activeFocusChanged()
+
+ This signal is emitted when this item gains active focus.
+*/
+
+/*!
+ \fn void QFxItem::baselineChanged()
+
+ This signal is emitted when the baseline of the item changes.
+
+ The baseline may change in response to a change to the baselineOffset
+ property or due to the geometry of the item changing.
+*/
+
+/*!
+ \fn void QFxItem::baselineOffsetChanged()
+
+ This signal is emitted when the baseline of the item is changed
+ via the baselineOffset property.
+
+ The baseline corresponds to the baseline of the text contained in
+ the item. It is useful for aligning the text in items placed
+ beside each other. The default baseline is positioned at
+ 2/3 of the height of the item.
+*/
+
+/*!
+ \fn void QFxItem::leftChanged()
+
+ This signal is emitted when the left coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::rightChanged()
+
+ This signal is emitted when the right coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::topChanged()
+
+ This signal is emitted when the top coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::bottomChanged()
+
+ This signal is emitted when the bottom coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::widthChanged()
+
+ This signal is emitted when the width of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::heightChanged()
+
+ This signal is emitted when the height of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::hcenterChanged()
+
+ This signal is emitted when the horizontal center coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::vcenterChanged()
+
+ This signal is emitted when the vertical center coordinate of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::scaleChanged()
+
+ This signal is emitted when the scale of the item changes.
+*/
+
+/*!
+ \fn void QFxItem::stateChanged(const QString &state)
+
+ This signal is emitted when the \a state of the item changes.
+
+ \sa states-transitions
+*/
+
+/*!
+ \qmlsignal Item::onKeyPress(event)
+
+ This handler is called when a key is pressed.
+
+ The key event is available via the KeyEvent \a event.
+
+ \qml
+ Item {
+ onKeyPress: { if (event.key == Qt.Key_Enter) state='Enter' }
+ }
+ \endqml
+*/
+
+/*!
+ \qmlsignal Item::onKeyRelease(event)
+
+ This handler is called when a key is released.
+
+ The key event is available in via the KeyEvent \a event.
+
+ \qml
+ Item {
+ onKeyRelease: { if (event.key == Qt.Key_Enter) state='Enter' }
+ }
+ \endqml
+*/
+
+/*!
+ \fn void QFxItem::visibleChanged()
+
+ This signal is emitted when the visibility of the item changes.
+
+ \sa setVisible()
+*/
+
+/*!
+ \fn void QFxItem::opacityChanged()
+
+ This signal is emitted when the opacity of the item changes.
+
+ \sa opacity(), setOpacity()
+*/
+
+/*!
+ \fn void QFxItem::parentChanged()
+
+ This signal is emitted when the parent of the item changes.
+
+ \sa setItemParent()
+*/
+
+/*!
+ \fn void QFxItem::focusChanged()
+
+ This signal is emitted when the item's focus state changes.
+
+ \sa QSimpleCanvasItem::setFocus()
+*/
+
+/*!
+ \fn QFxItem::QFxItem(QFxItem *parent)
+
+ Constructs a QFxItem with the given \a parent.
+*/
+QFxItem::QFxItem(QFxItem* parent)
+ : QSimpleCanvasItem(*(new QFxItemPrivate), parent)
+{
+ Q_D(QFxItem);
+ d->init(parent);
+}
+
+/*! \internal
+*/
+QFxItem::QFxItem(QFxItemPrivate &dd, QFxItem *parent)
+ : QSimpleCanvasItem(dd, parent)
+{
+ Q_D(QFxItem);
+ d->init(parent);
+}
+
+/*! \internal
+*/
+void QFxItem::doUpdate()
+{
+ update();
+}
+
+/*!
+ Destroys the QFxItem.
+*/
+QFxItem::~QFxItem()
+{
+ Q_D(QFxItem);
+ delete d->_anchorLines; d->_anchorLines = 0;
+}
+
+/*!
+ \qmlproperty enum Item::transformOrigin
+ This property holds the origin point around which scale and rotation transform.
+
+ Nine transform origins are available, as shown in the image below.
+
+ \image declarative-transformorigin.png
+
+ This example scales an image about its center.
+ \qml
+ Image {
+ source: "myimage.png"
+ transformOrigin: "Center"
+ scale: 4
+ }
+ \endqml
+
+ The default transform origin is \c TopLeft.
+*/
+
+/*!
+ \qmlproperty Item Item::parent
+ This property holds the parent of the item.
+*/
+
+/*!
+ \property QFxItem::parent
+ This property holds the parent of the item.
+*/
+void QFxItem::setItemParent(QFxItem *parent)
+{
+ setParent(parent);
+}
+
+/*!
+ \internal
+ \property QFxItem::moveToParent
+ Playing around with view2view transitions.
+ */
+
+/*!
+ \internal
+ */
+void QFxItem::moveToParent(QFxItem *parent)
+{
+ if (parent && itemParent()) {
+ QPointF me = itemParent()->mapToScene(QPointF(0,0));
+ QPointF them = parent->mapToScene(QPointF(0,0));
+
+ QPointF themx = parent->mapToScene(QPointF(1,0));
+ QPointF themy = parent->mapToScene(QPointF(0,1));
+
+ themx -= them;
+ themy -= them;
+
+ setItemParent(parent);
+
+ // XXX - this is silly and will only work in a few cases
+
+ /*
+ xDiff = rx * themx_x + ry * themy_x
+ yDiff = rx * themx_y + ry * themy_y
+ */
+
+ qreal rx = 0;
+ qreal ry = 0;
+ qreal xDiff = them.x() - me.x();
+ qreal yDiff = them.y() - me.y();
+
+
+ if (themx.x() == 0.) {
+ ry = xDiff / themy.x();
+ rx = (yDiff - ry * themy.y()) / themx.y();
+ } else if (themy.x() == 0.) {
+ rx = xDiff / themx.x();
+ ry = (yDiff - rx * themx.y()) / themy.y();
+ } else if (themx.y() == 0.) {
+ ry = yDiff / themy.y();
+ rx = (xDiff - ry * themy.x()) / themx.x();
+ } else if (themy.y() == 0.) {
+ rx = yDiff / themx.y();
+ ry = (xDiff - rx * themx.x()) / themy.x();
+ } else {
+ qreal div = (themy.x() * themx.y() - themy.y() * themx.x());
+
+ if (div != 0.)
+ rx = (themx.y() * xDiff - themx.x() * yDiff) / div;
+
+ if (themy.y() != 0.) ry = (yDiff - rx * themx.y()) / themy.y();
+ }
+
+ setX(x() - rx);
+ setY(y() - ry);
+ } else {
+ setItemParent(parent);
+ }
+}
+
+/*!
+ Returns the QFxItem parent of this item.
+*/
+QFxItem *QFxItem::itemParent() const
+{
+ return qobject_cast<QFxItem *>(QObject::parent());
+}
+
+/*!
+ \qmlproperty list<Item> Item::children
+ \qmlproperty list<Object> Item::resources
+
+ The children property contains the list of visual children of this item.
+ The resources property contains non-visual resources that you want to
+ reference by name.
+
+ Generally you can rely on Item's default property to handle all this for
+ you, but it can come in handy in some cases.
+
+ \qml
+ Item {
+ children: [
+ Text {},
+ Rect {}
+ ]
+ resources: [
+ Component {
+ id: myComponent
+ Text {}
+ }
+ ]
+ }
+ \endqml
+*/
+
+/*!
+ \property QFxItem::children
+
+ This property contains the list of visual children of this item.
+*/
+
+/*!
+ \property QFxItem::resources
+
+ This property contains non-visual resources that you want to
+ reference by name.
+*/
+
+/*!
+ Returns true if all of the attributes set via QML have been set;
+ otherwise returns false.
+
+ \sa classComplete()
+*/
+bool QFxItem::isClassComplete() const
+{
+ Q_D(const QFxItem);
+ return d->_classComplete;
+}
+
+/*!
+ Returns true if construction of the QML component is complete; otherwise
+ returns false.
+
+ It is often desireable to delay some processing until the component is
+ completed.
+
+ \sa componentComplete()
+*/
+bool QFxItem::isComponentComplete() const
+{
+ Q_D(const QFxItem);
+ return d->_componentComplete;
+}
+
+/*!
+ \property QFxItem::anchors
+ \brief The anchors (alignments) used by the item.
+*/
+QFxAnchors *QFxItem::anchors()
+{
+ Q_D(QFxItem);
+ return d->anchors();
+}
+
+void QFxItemPrivate::data_removeAt(int)
+{
+ // ###
+}
+
+int QFxItemPrivate::data_count() const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::data_append(QObject *o)
+{
+ Q_Q(QFxItem);
+ QFxItem *i = qobject_cast<QFxItem *>(o);
+ if (i)
+ q->children()->append(i);
+ else
+ resources_append(o);
+}
+
+void QFxItemPrivate::data_insert(int, QObject *)
+{
+ // ###
+}
+
+QObject *QFxItemPrivate::data_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::data_clear()
+{
+ // ###
+}
+
+void QFxItemPrivate::resources_removeAt(int)
+{
+ // ###
+}
+
+int QFxItemPrivate::resources_count() const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::resources_append(QObject *o)
+{
+ Q_Q(QFxItem);
+ o->setParent(q);
+}
+
+void QFxItemPrivate::resources_insert(int, QObject *)
+{
+ // ###
+}
+
+QObject *QFxItemPrivate::resources_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::resources_clear()
+{
+ // ###
+}
+
+void QFxItemPrivate::children_removeAt(int)
+{
+ // ###
+}
+
+int QFxItemPrivate::children_count() const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::children_append(QFxItem *i)
+{
+ Q_Q(QFxItem);
+ i->setParent(q);
+}
+
+void QFxItemPrivate::children_insert(int, QFxItem *)
+{
+ // ###
+}
+
+QFxItem *QFxItemPrivate::children_at(int) const
+{
+ // ###
+ return 0;
+}
+
+void QFxItemPrivate::children_clear()
+{
+ // ###
+}
+
+/*!
+ \qmlproperty list<Object> Item::data
+ \default
+
+ The data property is allows you to freely mix visual children and resources
+ of an item. If you assign a visual item to the data list it becomes
+ a child and if you assign any other object type, it is added as a resource.
+
+ So you can write:
+ \qml
+ Item {
+ Text {}
+ Rect {}
+ Script {}
+ }
+ \endqml
+
+ instead of:
+ \qml
+ Item {
+ children: [
+ Text {},
+ Rect {}
+ ]
+ resources: [
+ Script {}
+ ]
+ }
+ \endqml
+
+ data is a behind-the-scenes property: you should never need to explicitly
+ specify it.
+ */
+
+/*!
+ \property QFxItem::data
+
+ The data property is allows you to freely mix the visual children
+ and the non-visual resources of an item. If you assign a visual
+ item to the data list it becomes a child and if you assign any
+ other object type, it is added as a resource.
+
+ data is a behind-the-scenes property: you should never need to
+ explicitly specify it.
+ */
+QmlList<QObject *> *QFxItem::data()
+{
+ Q_D(QFxItem);
+ return &d->data;
+}
+
+/*!
+ \property QFxItem::contents
+ \brief An object that knows about the size of an item's children.
+
+ contents provides an easy way to access the (collective) width and
+ height of the item's children.
+*/
+QFxContents *QFxItem::contents()
+{
+ Q_D(QFxItem);
+ if (!d->_contents) {
+ d->_contents = new QFxContents;
+ d->_contents->setParent(this);
+ d->_contents->setItem(this);
+ }
+ return d->_contents;
+}
+
+/*!
+ \internal
+ \property QFxItem::qmlItem
+*/
+
+/*! \fn QFxItem *QFxItem::qmlItem() const
+ \internal
+ */
+QFxItem *QFxItem::qmlItem() const
+{
+ Q_D(const QFxItem);
+ return d->qmlItem;
+}
+
+/*!
+ \qmlproperty string Item::qml
+ This property holds the dynamic QML for the item.
+
+ This property is used for dynamically loading QML into the
+ item. Querying for the QML only has meaning if the QML has been
+ dynamically set; otherwise an empty string is returned.
+*/
+
+/*! \fn void QFxItem::qmlChanged()
+ This signal is emitted whenever the item's dynamic QML
+ string changes.
+
+ \sa setQml()
+ */
+
+/*!
+ \property QFxItem::qml
+ This property holds the dynamic QML for the item.
+
+ This property is used for dynamically loading QML into the
+ item. Querying for the QML only has meaning if the QML has been
+ dynamically set; otherwise an empty string is returned.
+*/
+QString QFxItem::qml() const
+{
+ Q_D(const QFxItem);
+ return d->_qml;
+}
+
+void QFxItem::setQml(const QString &qml)
+{
+ Q_D(QFxItem);
+ if (d->_qml == qml)
+ return;
+
+ if (!d->_qml.isEmpty()) {
+ QmlChildren::Iterator iter = d->_qmlChildren.find(d->_qml);
+ if (iter != d->_qmlChildren.end())
+ (*iter)->setOpacity(0.);
+ }
+
+ d->_qml = qml;
+ d->_qmlurl = qmlContext(this)->resolvedUri(qml);
+ d->qmlItem = 0;
+
+ if (d->_qml.isEmpty()) {
+ emit qmlChanged();
+ return;
+ }
+
+ QmlChildren::Iterator iter = d->_qmlChildren.find(d->_qml);
+ if (iter != d->_qmlChildren.end()) {
+ (*iter)->setOpacity(1.);
+ d->qmlItem = (*iter);
+ emit qmlChanged();
+ } else {
+ d->_qmlcomp =
+ new QmlComponent(qmlEngine(this), d->_qmlurl, this);
+ if (!d->_qmlcomp->isLoading())
+ qmlLoaded();
+ else
+ QObject::connect(d->_qmlcomp, SIGNAL(statusChanged(QmlComponent::Status)),
+ this, SLOT(qmlLoaded()));
+ }
+}
+
+/*! \fn void QFxItem::newChildCreated(const QString &url, QScriptValue v)
+ This signal is emitted with the \a url and the script value \a v,
+ when a new child is created.
+ */
+
+/*!
+ \internal
+ */
+void QFxItem::qmlLoaded()
+{
+ Q_D(QFxItem);
+
+ { // newChild...
+ // ###
+ for (int i=0; i<d->_qmlnewloading.length(); ++i) {
+ QmlComponent *c = d->_qmlnewcomp.at(i);
+ if (c->isLoading())
+ continue;
+
+ QmlContext *ctxt = new QmlContext(qmlContext(this));
+ QObject* o = c ? c->create(ctxt):0;
+ QFxItem* ret = qobject_cast<QFxItem*>(o);
+ if (ret) {
+ ret->setItemParent(this);
+ QScriptValue v = qmlEngine(this)->scriptEngine()->newQObject(ret);
+ emit newChildCreated(d->_qmlnewloading.at(i).toString(),v);
+ }
+
+ delete c;
+ d->_qmlnewloading.removeAt(i);
+ d->_qmlnewcomp.removeAt(i);
+ --i;
+ }
+ }
+
+ // setQml...
+ if (d->_qmlcomp) {
+ QmlContext *ctxt = new QmlContext(qmlContext(this));
+ ctxt->addDefaultObject(this);
+
+ QObject *obj = d->_qmlcomp->create(ctxt);
+ QFxItem *qmlChild = qobject_cast<QFxItem *>(obj);
+ if (qmlChild) {
+ qmlChild->setItemParent(this);
+ d->_qmlChildren.insert(d->_qml, qmlChild);
+ d->qmlItem = qmlChild;
+ } else {
+ delete qmlChild;
+ d->_qml = QString();
+ }
+ delete d->_qmlcomp;
+ d->_qmlcomp = 0;
+ emit qmlChanged();
+ }
+}
+
+/*!
+ \qmlproperty real Item::x
+ \qmlproperty real Item::y
+ \qmlproperty int Item::width
+ \qmlproperty int Item::height
+
+ Defines the item's position and size relative to its parent.
+
+ \qml
+ Item { x: 100; y: 100; width: 100; height: 100 }
+ \endqml
+ */
+
+/*!
+ \property QFxItem::width
+
+ Defines the item's width relative to its parent.
+ */
+
+/*!
+ \property QFxItem::height
+
+ Defines the item's height relative to its parent.
+ */
+
+/*!
+ \property QFxItem::x
+
+ The x coordinate of the item relative to its parent.
+*/
+
+/*!
+ \property QFxItem::y
+
+ The y coordinate of the item relative to its parent.
+*/
+
+/*!
+ \property QFxItem::z
+
+ The z coordinate of the item relative to its parent.
+
+ A negative z coordinate means the item will be painted below its parent.
+*/
+
+
+/*!
+ \qmlproperty real Item::z
+
+ Sets the stacking order of the item. By default the stacking order is 0.
+
+ Items with a higher stacking value are drawn on top of items with a
+ lower stacking order. Items with the same stacking value are drawn
+ bottom up in the order they appear. Items with a negative stacking
+ value are drawn under their parent's content.
+
+ The following example shows the various effects of stacking order.
+
+ \table
+ \row
+ \o \image declarative-item_stacking1.png
+ \o Same \c z - later children above earlier children:
+ \qml
+ Item {
+ Rect {
+ color: "red"
+ width: 100; height: 100
+ }
+ Rect {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking2.png
+ \o Higher \c z on top:
+ \qml
+ Item {
+ Rect {
+ z: 1
+ color: "red"
+ width: 100; height: 100
+ }
+ Rect {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking3.png
+ \o Same \c z - children above parents:
+ \qml
+ Item {
+ Rect {
+ color: "red"
+ width: 100; height: 100
+ Rect {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking4.png
+ \o Lower \c z below:
+ \qml
+ Item {
+ Rect {
+ color: "red"
+ width: 100; height: 100
+ Rect {
+ z: -1
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \endtable
+ */
+
+/*!
+ This function is called to handle this item's changes in
+ geometry from \a oldGeometry to \a newGeometry. If the two
+ geometries are the same, it doesn't do anything.
+ */
+void QFxItem::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QFxItem);
+ if (newGeometry.width() != oldGeometry.width()) {
+ int xoffset = oldGeometry.width() - newGeometry.width();
+ d->handleWidthChange(xoffset);
+ }
+
+ if (newGeometry.height() != oldGeometry.height()) {
+ int yoffset = oldGeometry.height() - newGeometry.height();
+ d->handleHeightChange(yoffset);
+ }
+
+ if (newGeometry.x() != oldGeometry.x()) {
+ emit leftChanged();
+ emit hcenterChanged();
+ emit rightChanged();
+ }
+
+ if (newGeometry.y() != oldGeometry.y()) {
+ emit topChanged();
+ emit vcenterChanged();
+ emit bottomChanged();
+ }
+}
+
+void QFxItemPrivate::handleWidthChange(int xoffset)
+{
+ Q_Q(QFxItem);
+ if (!_anchors) {
+ emit q->hcenterChanged();
+ emit q->rightChanged();
+ } else {
+ QFxAnchors::UsedAnchors used = anchors()->usedAnchors();
+ if (used & QFxAnchors::HasHCenterAnchor) {
+ q->setX(q->x() + xoffset/2);
+ emit q->rightChanged();
+ } else if ((used & QFxAnchors::HasRightAnchor) && !(used & QFxAnchors::HasLeftAnchor)) {
+ q->setX(q->x() + xoffset);
+ emit q->hcenterChanged();
+ } else {
+ emit q->hcenterChanged();
+ emit q->rightChanged();
+ }
+ }
+ if (q->rotation() && q->transformOrigin() != QFxItem::TopLeft)
+ q->setRotation(q->rotation());
+ if (q->scale() && q->transformOrigin() != QFxItem::TopLeft)
+ q->setScale(q->scale());
+ emit q->widthChanged();
+}
+
+void QFxItemPrivate::handleHeightChange(int yoffset)
+{
+ Q_Q(QFxItem);
+ if (!_anchors) {
+ emit q->vcenterChanged();
+ emit q->bottomChanged();
+ emit q->baselineChanged();
+ } else {
+ QFxAnchors::UsedAnchors used = anchors()->usedAnchors();
+ if (used & QFxAnchors::HasBaselineAnchor) {
+ q->setY(q->y() + yoffset - q->baselineOffset());
+ emit q->bottomChanged();
+ emit q->vcenterChanged();
+ } else if (used & QFxAnchors::HasVCenterAnchor) {
+ q->setY(q->y() + yoffset/2);
+ emit q->bottomChanged();
+ } else if ((used & QFxAnchors::HasBottomAnchor) && !(used & QFxAnchors::HasTopAnchor)) {
+ q->setY(q->y() + yoffset);
+ emit q->vcenterChanged();
+ } else {
+ emit q->vcenterChanged();
+ emit q->bottomChanged();
+ emit q->baselineChanged();
+ }
+ }
+ if (q->rotation() && q->transformOrigin() != QFxItem::TopLeft)
+ q->setRotation(q->rotation());
+ if (q->scale() && q->transformOrigin() != QFxItem::TopLeft)
+ q->setScale(q->scale());
+ emit q->heightChanged();
+}
+
+/*!
+ \qmlproperty bool Item::flipVertically
+ \qmlproperty bool Item::flipHorizontally
+
+ When set, the item will be displayed flipped horizontally or vertically
+ about its center.
+ */
+
+/*!
+ \property QFxItem::flipVertically
+
+ When set, the item will be displayed flipped horizontally or vertically
+ about its center.
+ */
+bool QFxItem::flipVertically() const
+{
+ return flip() & VerticalFlip;
+}
+
+void QFxItem::setFlipVertically(bool v)
+{
+ if (v)
+ setFlip((QSimpleCanvasItem::Flip)(flip() | VerticalFlip));
+ else
+ setFlip((QSimpleCanvasItem::Flip)(flip() & ~VerticalFlip));
+}
+
+/*!
+ \property QFxItem::flipHorizontally
+
+ When set, the item will be displayed flipped horizontally or vertically
+ about its center.
+ */
+bool QFxItem::flipHorizontally() const
+{
+ return flip() & HorizontalFlip;
+}
+
+void QFxItem::setFlipHorizontally(bool v)
+{
+ if (v)
+ setFlip((QSimpleCanvasItem::Flip)(flip() | HorizontalFlip));
+ else
+ setFlip((QSimpleCanvasItem::Flip)(flip() & ~HorizontalFlip));
+}
+
+/*! \fn void QFxItem::keyPress(QFxKeyEvent *event)
+ This signal is emitted by keyPressEvent() for the \a event.
+ */
+
+/*! \fn void QFxItem::keyRelease(QFxKeyEvent *event)
+ This signal is emitted by keyReleaseEvent() for the \a event.
+ */
+
+/*!
+ \reimp
+*/
+void QFxItem::keyPressEvent(QKeyEvent *event)
+{
+ QFxKeyEvent ke(*event);
+ emit keyPress(&ke);
+ event->setAccepted(ke.isAccepted());
+ if (itemParent() && !ke.isAccepted())
+ itemParent()->keyPressEvent(event);
+}
+
+/*!
+ \reimp
+*/
+void QFxItem::keyReleaseEvent(QKeyEvent *event)
+{
+ QFxKeyEvent ke(*event);
+ emit keyRelease(&ke);
+ event->setAccepted(ke.isAccepted());
+ if (itemParent() && !ke.isAccepted())
+ itemParent()->keyReleaseEvent(event);
+}
+
+/*!
+ Returns the bounding rectangle of the item in scene coordinates.
+*/
+QRectF QFxItem::sceneBoundingRect() const
+{
+ return QRectF(mapToScene(QPointF(0,0)), QSize(width(), height()));
+}
+
+/*!
+ \qmlproperty string Item::id
+ This property holds the identifier for the item.
+
+ The identifier can be used in bindings and other expressions to
+ refer to the item. For example:
+
+ \qml
+ Text { id: myText; ... }
+ Text { text: myText.text }
+ \endqml
+
+ The identifier is available throughout to the \l {components}{component}
+ where it is declared. The identifier must be unique in thecomponent.
+*/
+
+/*!
+ \property QFxItem::id
+ This property holds the identifier for the item.
+
+ The identifier can be used in bindings and other expressions to
+ refer to the item. For example:
+
+ \qml
+ Text { id: myText; ... }
+ Text { text: myText.text }
+ \endqml
+
+ The identifier is available throughout the \l {components}{component}
+ where it is declared. The identifier must be unique in thecomponent.
+*/
+QString QFxItem::id() const
+{
+ Q_D(const QFxItem);
+ return d->_id;
+}
+
+void QFxItem::setId(const QString &id)
+{
+ Q_D(QFxItem);
+ setObjectName(id);
+ d->_id = id;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::left() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->left;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::right() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->right;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::horizontalCenter() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->hCenter;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::top() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->top;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::bottom() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->bottom;
+}
+
+/*!
+ \internal
+*/
+QFxAnchorLine QFxItem::verticalCenter() const
+{
+ Q_D(const QFxItem);
+ return d->anchorLines()->vCenter;
+}
+
+/*!
+ \property QFxItem::top
+
+ One of the anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QFxItem::bottom
+
+ One of the anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QFxItem::left
+
+ One of the anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QFxItem::right
+
+ One of the anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QFxItem::horizontalCenter
+
+ One of the anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QFxItem::verticalCenter
+
+ One of the anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \qmlproperty AnchorLine Item::top
+ \qmlproperty AnchorLine Item::bottom
+ \qmlproperty AnchorLine Item::left
+ \qmlproperty AnchorLine Item::right
+ \qmlproperty AnchorLine Item::horizontalCenter
+ \qmlproperty AnchorLine Item::verticalCenter
+
+ The anchor lines of the item.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \qmlproperty AnchorLine Item::anchors.top
+ \qmlproperty AnchorLine Item::anchors.bottom
+ \qmlproperty AnchorLine Item::anchors.left
+ \qmlproperty AnchorLine Item::anchors.right
+ \qmlproperty AnchorLine Item::anchors.horizontalCenter
+ \qmlproperty AnchorLine Item::anchors.verticalCenter
+
+ \qmlproperty Item Item::anchors.fill
+
+ \qmlproperty int Item::anchors.topMargin
+ \qmlproperty int Item::anchors.bottomMargin
+ \qmlproperty int Item::anchors.leftMargin
+ \qmlproperty int Item::anchors.rightMargin
+ \qmlproperty int Item::anchors.horizontalCenterOffset
+ \qmlproperty int Item::anchors.verticalCenterOffset
+
+ Anchors provide a way to position an item by specifying its
+ relationship with other items.
+
+ Margins apply to top, bottom, left, right, and fill anchors.
+
+ Offsets apply for horizontal and vertical center anchors.
+
+ \table
+ \row
+ \o \image declarative-anchors_example.png
+ \o Text anchored to Image, horizontally centered and vertically below, with a margin.
+ \qml
+ Image { id: pic; ... }
+ Text {
+ id: label
+ anchors.horizontalCenter: pic.horizontalCenter
+ anchors.top: pic.bottom
+ anchors.topMargin: 5
+ ...
+ }
+ \endqml
+ \row
+ \o \image declarative-anchors_example2.png
+ \o
+ Left of Text anchored to right of Image, with a margin. The y
+ property of both defaults to 0.
+
+ \qml
+ Image { id: pic; ... }
+ Text {
+ id: label
+ anchors.left: pic.right
+ anchors.leftMargin: 5
+ ...
+ }
+ \endqml
+ \endtable
+
+ anchors.fill provides a convenient way for one item to have the
+ same geometry as another item, and is equivalent to connecting all
+ four directional anchors.
+
+ \note You can only anchor an item to siblings or a parent.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QFxItem::baselineOffset
+ \brief The position of the item's baseline in global (scene) coordinates.
+
+ The baseline of a Text item is the imaginary line on which the text
+ sits. Controls containing text usually set their baseline to the
+ baseline of their text.
+
+ For non-text items, a default baseline offset of two-thirds of the
+ item's height is used to determine the baseline.
+*/
+int QFxItem::baselineOffset() const
+{
+ Q_D(const QFxItem);
+ if (!d->_baselineOffset.isValid()) {
+ return height()*2/3; //### default baseline is 2/3 of the way to the bottom of the item
+ } else
+ return d->_baselineOffset;
+}
+
+/*!
+ \internal
+*/
+void QFxItem::setBaselineOffset(int offset)
+{
+ Q_D(QFxItem);
+ if (offset == d->_baselineOffset)
+ return;
+
+ d->_baselineOffset = offset;
+ emit baselineOffsetChanged();
+ emit baselineChanged();
+}
+
+/*!
+ \qmlproperty real Item::rotation
+ This property holds the rotation of the item in degrees.
+
+ This specifies how many degrees to rotate the item around its origin (0,0).
+ The default rotation is 0 degrees (i.e. not rotated at all).
+
+ \table
+ \row
+ \o \image declarative-rotation.png
+ \o
+ \qml
+ Rect {
+ color: "blue"
+ width: 100; height: 100
+ Rect {
+ color: "green"
+ width: 25; height: 25
+ }
+ Rect {
+ color: "red"
+ x: 25; y: 25; width: 50; height: 50
+ rotation: 30
+ }
+ }
+ \endqml
+ \endtable
+*/
+
+/*! \fn void QFxItem::rotationChanged()
+ This signal is emitted when the rotation property is changed.
+
+ \sa setRotation()
+ */
+
+/*!
+ \property QFxItem::rotation
+ This property holds the rotation of the item in degrees.
+
+ This specifies how many degrees to rotate the item around its origin (0,0).
+ The default rotation is 0 degrees (i.e. not rotated at all).
+*/
+qreal QFxItem::rotation() const
+{
+ Q_D(const QFxItem);
+ return d->_rotation;
+}
+
+void QFxItem::setRotation(qreal rotation)
+{
+ Q_D(QFxItem);
+ if (d->_rotation == rotation)
+ return;
+ d->_rotation = rotation;
+#if defined(QFX_RENDER_OPENGL)
+ QMatrix4x4 trans;
+ QPointF to = transformOriginPoint();
+ trans.translate(to.x(), to.y());
+ trans.rotate(d->_rotation, 0, 0, 1);
+ trans.translate(-to.x(), -to.y());
+#else
+ QTransform trans;
+ QPointF to = transformOriginPoint();
+ trans.translate(to.x(), to.y());
+ trans.rotate(d->_rotation);
+ trans.translate(-to.x(), -to.y());
+#endif
+ setTransform(trans);
+ emit rotationChanged();
+}
+
+/*!
+ \qmlproperty real Item::scale
+ This property holds the scale of the item.
+
+ A scale of less than 1 means the item will be displayed smaller than
+ normal, and a scale of greater than 1 means the item will be
+ displayed larger than normal. A negative scale means the item will
+ be mirrored.
+
+ By default, items are displayed at a scale of 1 (i.e. at their
+ normal size).
+
+ Scaling is from the item's origin (0,0).
+
+ \table
+ \row
+ \o \image declarative-scale.png
+ \o
+ \qml
+ Rect {
+ color: "blue"
+ width: 100; height: 100
+ Rect {
+ color: "green"
+ width: 25; height: 25
+ }
+ Rect {
+ color: "red"
+ x: 25; y: 25; width: 50; height: 50
+ scale: 1.4
+ }
+ }
+ \endqml
+ \endtable
+*/
+
+/*!
+ \property QFxItem::scale
+ This property holds the scale of the item.
+
+ A scale of less than 1 means the item will be displayed smaller than
+ normal, and a scale of greater than 1 means the item will be
+ displayed larger than normal. A negative scale means the item will
+ be mirrored.
+
+ By default, items are displayed at a scale of 1 (i.e. at their
+ normal size).
+
+ Scaling is from the item's origin (0,0).
+*/
+qreal QFxItem::scale() const
+{
+ return QSimpleCanvasItem::scale();
+}
+
+void QFxItem::setScale(qreal s)
+{
+ if (QSimpleCanvasItem::scale() == s) return;
+ QSimpleCanvasItem::setScale(s);
+ emit scaleChanged();
+ update();
+}
+
+/*!
+ \qmlproperty real Item::opacity
+
+ The opacity of the item. Opacity is specified as a number between 0
+ (fully transparent) and 1 (fully opaque). The default is 1.
+
+ Opacity is an \e inherited attribute. That is, the opacity is
+ also applied individually to child items. In almost all cases this
+ is what you want. If you can spot the issue in the following
+ example, you might need to use an opacity filter (not yet available) instead.
+
+ \table
+ \row
+ \o \image declarative-item_opacity1.png
+ \o
+ \qml
+ Item {
+ Rect {
+ color: "red"
+ width: 100; height: 100
+ Rect {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_opacity2.png
+ \o
+ \qml
+ Item {
+ Rect {
+ opacity: 0.5
+ color: "red"
+ width: 100; height: 100
+ Rect {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \endtable
+*/
+
+/*!
+ \property QFxItem::opacity
+
+ The opacity of the item. Opacity is specified as a number between 0
+ (fully transparent) and 1 (fully opaque). The default is 1.
+
+ Opacity is an \e inherited attribute. That is, the opacity is
+ also applied individually to child items.
+*/
+
+qreal QFxItem::opacity() const
+{
+ return QSimpleCanvasItem::visible();
+}
+
+void QFxItem::setOpacity(qreal v)
+{
+ if (v == QSimpleCanvasItem::visible())
+ return;
+
+ if (v < 0) v = 0;
+ else if (v > 1) v = 1;
+ QSimpleCanvasItem::setVisible(v);
+
+ emit opacityChanged();
+}
+
+/*!
+ Returns a value indicating whether the mouse should
+ remain with this item.
+ */
+bool QFxItem::keepMouseGrab() const
+{
+ Q_D(const QFxItem);
+ return d->_keepMouse;
+}
+
+/*!
+ The flag indicating whether the mouse should remain
+ with this item is set to \a keep.
+ */
+void QFxItem::setKeepMouseGrab(bool keep)
+{
+ Q_D(QFxItem);
+ d->_keepMouse = keep;
+}
+
+/*!
+ This function emits the \e activeFocusChanged signal.
+ \a flag is not used.
+ */
+void QFxItem::activeFocusChanged(bool flag)
+{
+ emit activeFocusChanged();
+}
+
+/*!
+ This function emits the \e focusChanged signal.
+ \a flag is not used.
+ */
+void QFxItem::focusChanged(bool flag)
+{
+ emit focusChanged();
+}
+
+QmlList<QFxItem *> *QFxItem::children()
+{
+ Q_D(QFxItem);
+ return &(d->children);
+}
+
+QmlList<QObject *> *QFxItem::resources()
+{
+ Q_D(QFxItem);
+ return &(d->resources);
+}
+
+/*!
+ \qmlproperty list<State> Item::states
+ This property holds a list of states defined by the item.
+
+ \qml
+ Item {
+ states: [
+ State { ... },
+ State { ... }
+ ...
+ ]
+ }
+ \endqml
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+/*!
+ \property QFxItem::states
+ This property holds a list of states defined by the item.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+QmlList<QmlState *>* QFxItem::states()
+{
+ Q_D(QFxItem);
+ return d->states()->statesProperty();
+}
+
+/*!
+ \qmlproperty list<Transition> Item::transitions
+ This property holds a list of transitions defined by the item.
+
+ \qml
+ Item {
+ transitions: [
+ Transition { ... },
+ Transition { ... }
+ ...
+ ]
+ }
+ \endqml
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+/*!
+ \property QFxItem::transitions
+ This property holds a list of transitions defined by the item.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+QmlList<QmlTransition *>* QFxItem::transitions()
+{
+ Q_D(QFxItem);
+ return d->states()->transitionsProperty();
+}
+
+/*!
+ \internal
+ \property QFxItem::filter
+*/
+
+/*!
+ \qmlproperty list<Filter> Item::filter
+ This property holds a list of graphical filters to be applied to the item.
+
+ \l {Filter}{Filters} include things like \l {Blur}{blurring}
+ the item, or giving it a \l Reflection. Some
+ filters may not be available on all canvases; if a filter is not
+ available on a certain canvas, it will simply not be applied for
+ that canvas (but the QML will still be considered valid).
+
+ \qml
+ Item {
+ filter: [
+ Blur { ... },
+ Relection { ... }
+ ...
+ ]
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool Item::clip
+ This property holds whether clipping is enabled.
+
+ if clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ \property QFxItem::clip
+ This property holds whether clipping is enabled.
+
+ if clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ Returns the state with \a name. Returns 0 if no matching state is found.
+*/
+QmlState *QFxItem::findState(const QString &name) const
+{
+ Q_D(const QFxItem);
+ if (!d->_stateGroup)
+ return 0;
+ else
+ return d->_stateGroup->findState(name);
+}
+
+/*!
+ \qmlproperty string Item::state
+
+ This property holds the name of the current state of the item.
+
+ This property is often used in scripts to change between states. For
+ example:
+
+ \qml
+ Script {
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
+ }
+ }
+ \endqml
+
+ If the item is in its base state (i.e. no explicit state has been
+ set), \c state will be a blank string. Likewise, you can return an
+ item to its base state by setting its current state to \c ''.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+/*!
+ \property QFxItem::state
+
+ This property holds the name of the current state of the item.
+
+ This property is often used in scripts to change between states. For
+ example:
+
+ \qml
+ Script {
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
+ }
+ }
+ \endqml
+
+ If the item is in its base state (i.e. no explicit state has been
+ set), \c state will be a blank string. Likewise, you can return an
+ item to its base state by setting its current state to \c ''.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+QString QFxItem::state() const
+{
+ Q_D(const QFxItem);
+ if (!d->_stateGroup)
+ return QString();
+ else
+ return d->_stateGroup->state();
+}
+
+void QFxItem::setState(const QString &state)
+{
+ Q_D(QFxItem);
+ d->states()->setState(state);
+}
+
+/*!
+ \qmlproperty list<Transform> Item::transform
+ This property holds the list of transformations to apply.
+
+ For more information see \l Transform.
+*/
+
+/*!
+ \property QFxItem::transform
+ This property holds the list of transformations to apply.
+
+ For more information see \l Transform.
+*/
+QList<QFxTransform *> *QFxItem::transform()
+{
+ Q_D(QFxItem);
+ return &(d->_transform);
+}
+
+/*!
+ \property QFxItem::focus
+ This property holds the item's focus state.
+*/
+
+/*!
+ \property QFxItem::focusable
+ This property holds whether the item has focus state.
+*/
+
+/*!
+ Returns true if the item is visible; otherwise returns false.
+
+ An item is considered visible if its opacity is not 0.
+*/
+bool QFxItem::isVisible() const
+{
+ Q_D(const QFxItem);
+ return d->visible;
+}
+
+/*!
+ \property QFxItem::visible
+
+ This property specifies whether the item is visible or invisible.
+
+ Setting visibility to false sets opacity to 0. Setting the
+ visibility to true restores the opacity to its previous value.
+
+ \sa isVisible()
+*/
+void QFxItem::setVisible(bool visible)
+{
+ Q_D(QFxItem);
+ if (visible == d->visible)
+ return;
+
+ d->visible = visible;
+ if (visible)
+ setOpacity(d->visibleOp);
+ else {
+ d->visibleOp = opacity();
+ setOpacity(0);
+ }
+
+ emit visibleChanged();
+}
+
+/*! \internal
+*/
+void QFxItem::dump(int depth)
+{
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << metaObject()->className() << "(" << (void *)static_cast<QFxItem*>(this) << ", " << (void *)static_cast<QSimpleCanvasItem*>(this) << "):" << x() << y() << width() << height() << (void *) itemParent();
+}
+
+/*! \internal
+*/
+QString QFxItem::propertyInfo() const
+{
+ return QString();
+}
+
+/*!
+ Creates a new child of the given component \a type. The
+ newChildCreated() signal will be emitted when and if the child is
+ successfully created.
+
+ \preliminary
+*/
+void QFxItem::newChild(const QString &type)
+{
+ Q_D(QFxItem);
+
+ QUrl url = qmlContext(this)->resolvedUri(type);
+ if (url.isEmpty())
+ return;
+
+ d->_qmlnewloading.append(url);
+ d->_qmlnewcomp.append(new QmlComponent(qmlEngine(this), url, this));
+
+ if (!d->_qmlnewcomp.last()->isLoading())
+ qmlLoaded();
+ else
+ connect(d->_qmlnewcomp.last(), SIGNAL(statusChanged(QmlComponent::Status)),
+ this, SLOT(qmlLoaded()));
+}
+
+/*!
+ classBegin() is called when the item is constructed, but its
+ properties have not yet been set.
+
+ \sa classComplete(), componentComplete(), isClassComplete(), isComponentComplete()
+*/
+void QFxItem::classBegin()
+{
+ Q_D(QFxItem);
+ d->_classComplete = false;
+ d->_componentComplete = false;
+ if (d->_stateGroup)
+ d->_stateGroup->classBegin();
+}
+
+/*!
+ classComplete() is called when all properties specified in QML
+ have been assigned. It is sometimes desireable to delay some
+ processing until all property assignments are complete.
+*/
+void QFxItem::classComplete()
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ItemComponentComplete> cc;
+#endif
+ Q_D(QFxItem);
+ d->_classComplete = true;
+ if (d->_stateGroup)
+ d->_stateGroup->classComplete();
+}
+
+/*!
+ componentComplete() is called when all items in the component
+ have been constructed. It is often desireable to delay some
+ processing until the component is complete an all bindings in the
+ component have been resolved.
+*/
+void QFxItem::componentComplete()
+{
+ Q_D(QFxItem);
+ d->_componentComplete = true;
+ if (d->_stateGroup)
+ d->_stateGroup->componentComplete();
+ if (d->_anchors) {
+ d->anchors()->connectHAnchors();
+ d->anchors()->connectVAnchors();
+ }
+ if (!d->_transform.isEmpty())
+ updateTransform();
+}
+
+/*! \internal
+*/
+void QFxItem::parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *)
+{
+ emit parentChanged();
+}
+
+/*! \internal
+*/
+void QFxItem::reparentItems()
+{
+ qFatal("EEK");
+}
+
+/*!
+ \internal
+*/
+void QFxItem::updateTransform()
+{
+ Q_D(QFxItem);
+ QSimpleCanvas::Matrix trans;
+ for (int ii = d->_transform.count() - 1; ii >= 0; --ii) {
+ QFxTransform *a = d->_transform.at(ii);
+ if (!a->isIdentity())
+ trans = a->transform() * trans;
+ }
+
+ setTransform(trans);
+ transformChanged(trans);
+}
+
+/*!
+ \internal
+*/
+void QFxItem::transformChanged(const QSimpleCanvas::Matrix &)
+{
+}
+
+QmlStateGroup *QFxItemPrivate::states()
+{
+ Q_Q(QFxItem);
+ if (!_stateGroup) {
+ _stateGroup = new QmlStateGroup(q);
+ if (!_classComplete)
+ _stateGroup->classBegin();
+ QObject::connect(_stateGroup, SIGNAL(stateChanged(QString)),
+ q, SIGNAL(stateChanged(QString)));
+ }
+
+ return _stateGroup;
+}
+
+QFxItemPrivate::AnchorLines::AnchorLines(QFxItem *q)
+{
+ left.item = q;
+ left.anchorLine = QFxAnchorLine::Left;
+ right.item = q;
+ right.anchorLine = QFxAnchorLine::Right;
+ hCenter.item = q;
+ hCenter.anchorLine = QFxAnchorLine::HCenter;
+ top.item = q;
+ top.anchorLine = QFxAnchorLine::Top;
+ bottom.item = q;
+ bottom.anchorLine = QFxAnchorLine::Bottom;
+ vCenter.item = q;
+ vCenter.anchorLine = QFxAnchorLine::VCenter;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxitem.h b/src/declarative/fx/qfxitem.h
new file mode 100644
index 0000000..549c9c2
--- /dev/null
+++ b/src/declarative/fx/qfxitem.h
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXITEM_H
+#define QFXITEM_H
+
+#include <QObject>
+#include <QtScript/qscriptvalue.h>
+#include <QList>
+#include <QtDeclarative/qfxanchors.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qfxscalegrid.h>
+#include <QtDeclarative/qsimplecanvasitem.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlstate.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QFxContents : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int height READ height NOTIFY heightChanged);
+ Q_PROPERTY(int width READ width NOTIFY widthChanged);
+public:
+ QFxContents();
+
+ int height() const;
+
+ int width() const;
+
+ void setItem(QFxItem *item);
+
+public Q_SLOTS:
+ void calcHeight();
+ void calcWidth();
+
+Q_SIGNALS:
+ void heightChanged();
+ void widthChanged();
+
+private:
+ QFxItem *_item;
+ int _height;
+ int _width;
+};
+QML_DECLARE_TYPE(QFxContents);
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFxAnchors::UsedAnchors);
+
+class QmlState;
+class QmlTransition;
+class QFxTransform;
+class QFxKeyEvent;
+class QFxItemPrivate;
+class Q_DECLARATIVE_EXPORT QFxItem : public QSimpleCanvasItem, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QFxItem * parent READ itemParent WRITE setItemParent NOTIFY parentChanged DESIGNABLE false)
+ Q_PROPERTY(QFxItem * moveToParent READ itemParent WRITE moveToParent NOTIFY parentChanged DESIGNABLE false)
+ Q_PROPERTY(QString id READ id WRITE setId)
+ Q_PROPERTY(QmlList<QFxItem *>* children READ children DESIGNABLE false)
+ Q_PROPERTY(QmlList<QObject *>* resources READ resources DESIGNABLE false)
+ Q_PROPERTY(QFxAnchors * anchors READ anchors DESIGNABLE false)
+ Q_PROPERTY(QmlList<QObject *> *data READ data DESIGNABLE false)
+ Q_PROPERTY(QFxContents * contents READ contents DESIGNABLE false)
+ Q_PROPERTY(QmlList<QmlState *>* states READ states DESIGNABLE false)
+ Q_PROPERTY(QmlList<QmlTransition *>* transitions READ transitions DESIGNABLE false)
+ Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
+ Q_PROPERTY(QString qml READ qml WRITE setQml NOTIFY qmlChanged)
+ Q_PROPERTY(QFxItem *qmlItem READ qmlItem NOTIFY qmlChanged)
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY leftChanged)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY topChanged)
+ Q_PROPERTY(qreal z READ z WRITE setZ)
+ Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged)
+ Q_PROPERTY(bool flipVertically READ flipVertically WRITE setFlipVertically)
+ Q_PROPERTY(bool flipHorizontally READ flipHorizontally WRITE setFlipHorizontally)
+ Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged)
+ Q_PROPERTY(int baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged)
+ Q_PROPERTY(QFxAnchorLine left READ left)
+ Q_PROPERTY(QFxAnchorLine right READ right)
+ Q_PROPERTY(QFxAnchorLine horizontalCenter READ horizontalCenter)
+ Q_PROPERTY(QFxAnchorLine top READ top)
+ Q_PROPERTY(QFxAnchorLine bottom READ bottom)
+ Q_PROPERTY(QFxAnchorLine verticalCenter READ verticalCenter)
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
+ Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
+ Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged)
+ Q_PROPERTY(QSimpleCanvasFilter *filter READ filter WRITE setFilter)
+ Q_PROPERTY(bool clip READ clip WRITE setClip)
+ Q_PROPERTY(bool focusable READ isFocusable WRITE setFocusable)
+ Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged)
+ Q_PROPERTY(bool activeFocus READ hasActiveFocus NOTIFY activeFocusChanged)
+ Q_PROPERTY(QList<QFxTransform *>* transform READ transform)
+ Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+ typedef QHash<QString, QFxItem *> QmlChildren;
+
+public:
+ QFxItem(QFxItem *parent = 0);
+ virtual ~QFxItem();
+
+ QFxItem *itemParent() const;
+ void setItemParent(QFxItem *parent);
+
+ void moveToParent(QFxItem *parent);
+
+ QString id() const;
+ void setId(const QString &);
+
+ QmlList<QObject *> *data();
+ QmlList<QFxItem *> *children();
+ QmlList<QObject *> *resources();
+
+ QFxAnchors *anchors();
+
+ QFxContents *contents();
+
+ QmlList<QmlState *>* states();
+ QmlState *findState(const QString &name) const;
+
+ QmlList<QmlTransition *>* transitions();
+
+ QString state() const;
+ void setState(const QString &);
+
+ QFxItem *qmlItem() const;
+ QString qml() const;
+ void setQml(const QString &);
+
+ bool flipVertically() const;
+ void setFlipVertically(bool);
+ bool flipHorizontally() const;
+ void setFlipHorizontally(bool);
+
+ int baselineOffset() const;
+ void setBaselineOffset(int);
+
+ qreal rotation() const;
+ void setRotation(qreal);
+
+ qreal scale() const;
+ void setScale(qreal);
+
+ qreal opacity() const;
+ virtual void setOpacity(qreal);
+
+ QList<QFxTransform *> *transform();
+
+ bool isVisible() const;
+ void setVisible(bool);
+
+ virtual void dump(int depth = 0);
+ virtual QString propertyInfo() const;
+
+ bool isClassComplete() const;
+ bool isComponentComplete() const;
+
+ QRectF sceneBoundingRect() const;
+
+ void updateTransform();
+
+ bool keepMouseGrab() const;
+ void setKeepMouseGrab(bool);
+
+public Q_SLOTS:
+ void newChild(const QString &url);
+
+Q_SIGNALS:
+ void leftChanged();
+ void rightChanged();
+ void widthChanged();
+ void heightChanged();
+ void topChanged();
+ void bottomChanged();
+ void hcenterChanged();
+ void vcenterChanged();
+ void baselineChanged();
+ void baselineOffsetChanged();
+ void stateChanged(const QString &);
+ void focusChanged();
+ void activeFocusChanged();
+ void parentChanged();
+ void keyPress(QFxKeyEvent *event);
+ void keyRelease(QFxKeyEvent *event);
+ void rotationChanged();
+ void scaleChanged();
+ void opacityChanged();
+ void visibleChanged();
+ void qmlChanged();
+ void newChildCreated(const QString &url, QScriptValue);
+
+protected:
+ virtual void transformChanged(const QSimpleCanvas::Matrix &);
+ virtual void classBegin();
+ virtual void classComplete();
+ virtual void componentComplete();
+ virtual void parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *);
+ virtual void reparentItems();
+ virtual void focusChanged(bool);
+ virtual void activeFocusChanged(bool);
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *event);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+private Q_SLOTS:
+ void doUpdate();
+ void qmlLoaded();
+
+protected:
+ QFxItem(QFxItemPrivate &dd, QFxItem *parent = 0);
+
+private:
+ QFxAnchorLine left() const;
+ QFxAnchorLine right() const;
+ QFxAnchorLine horizontalCenter() const;
+ QFxAnchorLine top() const;
+ QFxAnchorLine bottom() const;
+ QFxAnchorLine verticalCenter() const;
+
+ void init(QFxItem *parent);
+ friend class QmlStatePrivate;
+ friend class QFxAnchors;
+ Q_DISABLE_COPY(QFxItem)
+ Q_DECLARE_PRIVATE(QFxItem)
+};
+QML_DECLARE_TYPE(QFxItem);
+
+QML_DECLARE_TYPE(QSimpleCanvasFilter);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXITEM_H
diff --git a/src/declarative/fx/qfxitem_p.h b/src/declarative/fx/qfxitem_p.h
new file mode 100644
index 0000000..f2da3ba
--- /dev/null
+++ b/src/declarative/fx/qfxitem_p.h
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXITEM_P_H
+#define QFXITEM_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 "qfxitem.h"
+#include <private/qsimplecanvasitem_p.h>
+#include <private/qmlnullablevalue_p.h>
+#include <qml.h>
+#include <qmlcontext.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkReply;
+
+class QFxItemPrivate : public QSimpleCanvasItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxItem)
+
+ typedef QHash<QString, QFxItem *> QmlChildren;
+
+public:
+ QFxItemPrivate()
+ : _anchors(0), _contents(0), qmlItem(0), _qmlcomp(0),
+ _baselineOffset(0), _rotation(0.),
+ _classComplete(true), _componentComplete(true), _keepMouse(false),
+ visible(true), _anchorLines(0), visibleOp(1), reparentedChildren(0),
+ _stateGroup(0)
+ {}
+ ~QFxItemPrivate()
+ { delete _anchors; }
+
+ void init(QFxItem *parent)
+ {
+ Q_Q(QFxItem);
+
+ if (parent)
+ q->setItemParent(parent);
+ _baselineOffset.invalidate();
+ q->setAcceptedMouseButtons(Qt::NoButton);
+ }
+
+ QString _id;
+
+ // data property
+ void data_removeAt(int);
+ int data_count() const;
+ void data_append(QObject *);
+ void data_insert(int, QObject *);
+ QObject *data_at(int) const;
+ void data_clear();
+ QML_DECLARE_LIST_PROXY(QFxItemPrivate, QObject *, data);
+
+ // resources property
+ void resources_removeAt(int);
+ int resources_count() const;
+ void resources_append(QObject *);
+ void resources_insert(int, QObject *);
+ QObject *resources_at(int) const;
+ void resources_clear();
+ QML_DECLARE_LIST_PROXY(QFxItemPrivate, QObject *, resources);
+
+ // children property
+ void children_removeAt(int);
+ int children_count() const;
+ void children_append(QFxItem *);
+ void children_insert(int, QFxItem *);
+ QFxItem *children_at(int) const;
+ void children_clear();
+ QML_DECLARE_LIST_PROXY(QFxItemPrivate, QFxItem *, children);
+
+ QList<QFxTransform *> _transform;
+ QFxAnchors *anchors() {
+ if (!_anchors) {
+ Q_Q(QFxItem);
+ _anchors = new QFxAnchors;
+ _anchors->setItem(q);
+ }
+ return _anchors;
+ }
+ QFxAnchors *_anchors;
+ QFxContents *_contents;
+ QFxItem *qmlItem;
+ QUrl _qmlurl;
+ QmlComponent *_qmlcomp;
+ QString _qml;
+ QList<QUrl> _qmlnewloading;
+ QList<QmlComponent*> _qmlnewcomp;
+
+ QmlNullableValue<int> _baselineOffset;
+ float _rotation;
+
+ bool _classComplete:1;
+ bool _componentComplete:1;
+ bool _keepMouse:1;
+ bool visible:1;
+
+ QmlChildren _qmlChildren;
+
+ struct AnchorLines {
+ AnchorLines(QFxItem *);
+ QFxAnchorLine left;
+ QFxAnchorLine right;
+ QFxAnchorLine hCenter;
+ QFxAnchorLine top;
+ QFxAnchorLine bottom;
+ QFxAnchorLine vCenter;
+ };
+ mutable AnchorLines *_anchorLines;
+ AnchorLines *anchorLines() const {
+ Q_Q(const QFxItem);
+ if (!_anchorLines) _anchorLines =
+ new AnchorLines(const_cast<QFxItem *>(q));
+ return _anchorLines;
+ }
+
+ float visibleOp;
+
+ int reparentedChildren;
+
+ QmlStateGroup *states();
+ QmlStateGroup *_stateGroup;
+
+ void handleWidthChange(int xoffset);
+ void handleHeightChange(int xoffset);
+};
+
+QT_END_NAMESPACE
+#endif // QFXITEM_P_H
diff --git a/src/declarative/fx/qfxkeyactions.cpp b/src/declarative/fx/qfxkeyactions.cpp
new file mode 100644
index 0000000..a07f047
--- /dev/null
+++ b/src/declarative/fx/qfxkeyactions.cpp
@@ -0,0 +1,920 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxkeyactions.h"
+#include <qmlexpression.h>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxKeyActions,KeyActions);
+
+class QFxKeyActionsPrivate
+{
+public:
+ QFxKeyActionsPrivate();
+
+ bool enabled;
+
+ uint keys1;
+ uint keys2;
+
+ QHash<Qt::Key, QString> actions;
+
+ bool key(Qt::Key) const;
+ QString action(Qt::Key) const;
+ void setKey(Qt::Key, bool = true);
+
+ bool testBit(int) const;
+ void setBit(int, bool);
+
+ int keyToBit(Qt::Key) const;
+
+ QString keyExpr(Qt::Key) const;
+ void setKeyExpr(Qt::Key, const QString &);
+};
+
+QFxKeyActionsPrivate::QFxKeyActionsPrivate()
+: enabled(true), keys1(0), keys2(0)
+{
+}
+
+int QFxKeyActionsPrivate::keyToBit(Qt::Key k) const
+{
+ if (k >= Qt::Key_A && k <= Qt::Key_Z ) {
+ return k - Qt::Key_A;
+ } else if (k >= Qt::Key_Left && k <= Qt::Key_Down) {
+ return 26 + k - Qt::Key_Left;
+ } else if (k >= Qt::Key_0 && k <= Qt::Key_9) {
+ return 30 + k - Qt::Key_0;
+ } else if (k >= Qt::Key_Context1 && k <= Qt::Key_Flip) {
+ return 40 + k - Qt::Key_Context1;
+ } else if (k >= Qt::Key_Select && k <= Qt::Key_No) {
+ return 47 + k - Qt::Key_Select;
+ } else {
+ const int start = 50;
+ switch(k) {
+ case Qt::Key_Escape:
+ return start + 0;
+ case Qt::Key_Return:
+ return start + 1;
+ case Qt::Key_Enter:
+ return start + 2;
+ case Qt::Key_Delete:
+ return start + 3;
+ case Qt::Key_Space:
+ return start + 4;
+ case Qt::Key_Back:
+ return start + 5;
+ case Qt::Key_unknown:
+ return start + 6;
+ case Qt::Key_Asterisk:
+ return start + 7;
+ default:
+ return -1;
+ }
+ }
+}
+
+bool QFxKeyActionsPrivate::key(Qt::Key k) const
+{
+ int b = keyToBit(k);
+ bool rv = testBit(b);
+ if (!rv && k != Qt::Key_Shift)
+ rv = testBit(keyToBit(Qt::Key_unknown));
+ return rv;
+}
+
+QString QFxKeyActionsPrivate::action(Qt::Key k) const
+{
+ int b = keyToBit(k);
+ if (b != -1 && testBit(b))
+ return actions.value(k);
+ else
+ return actions.value(Qt::Key_unknown);
+}
+
+void QFxKeyActionsPrivate::setKey(Qt::Key k, bool v)
+{
+ int b = keyToBit(k);
+ if (b == -1)
+ return;
+
+ setBit(b, v);
+}
+
+bool QFxKeyActionsPrivate::testBit(int b) const
+{
+ if (b < 0)
+ return false;
+
+ if (b < 32)
+ return keys1 & (1 << b);
+ else
+ return keys2 & (1 << (b - 32));
+}
+
+void QFxKeyActionsPrivate::setBit(int b, bool v)
+{
+ if (v) {
+ if (b < 32)
+ keys1 |= (1 << b);
+ else
+ keys2 |= (1 << (b - 32));
+ } else {
+ if (b < 32)
+ keys1 &= ~(1 << b);
+ else
+ keys2 &= ~(1 << (b - 32));
+ }
+}
+
+
+/*!
+ \qmlclass KeyActions
+ \brief The KeyActions item enables simple key handling.
+ \inherits Item
+
+ KeyActions is typically used in basic key handling scenarios where writing
+ JavaScript key handling routines would be unnecessarily complicated. The
+ KeyActions item has a collection of properties that correspond to a
+ selection of common keys. When a given key is pressed, the item executes
+ the action script assigned to the matching property. If no action has
+ been set the KeyActions item does nothing.
+
+ To receive (and susequently respond to) key presses, the KeyActions class
+ must be in the current focus chain, just like any other item.
+
+ For basic mouse handling, see \l MouseRegion.
+
+ KeyActions is an invisible item: it is never painted.
+*/
+QFxKeyActions::QFxKeyActions(QFxItem *parent)
+: QFxItem(parent), d(new QFxKeyActionsPrivate)
+{
+}
+
+QFxKeyActions::~QFxKeyActions()
+{
+ delete d;
+}
+
+QString QFxKeyActionsPrivate::keyExpr(Qt::Key k) const
+{
+ if (key(k))
+ return actions.value(k);
+ else
+ return QString();
+}
+
+void QFxKeyActionsPrivate::setKeyExpr(Qt::Key k, const QString &expr)
+{
+ if (expr.isEmpty()) {
+ if (key(k)) {
+ actions.remove(k);
+ setKey(k, false);
+ }
+ } else {
+ actions.insert(k, expr);
+ setKey(k);
+ }
+}
+
+/*!
+ \qmlproperty bool KeyActions::enabled
+
+ Enables or disables KeyActions' key handling. When not enabled, the
+ KeyActions instance does not respond to any key presses. The item is
+ enabled by default.
+*/
+bool QFxKeyActions::enabled() const
+{
+ return d->enabled;
+}
+
+void QFxKeyActions::setEnabled(bool e)
+{
+ if (d->enabled == e)
+ return;
+
+ d->enabled = e;
+ emit enabledChanged();
+}
+
+/*!
+ \qmlproperty string KeyActions::keyA...keyZ
+
+ The action to take for the given letter.
+
+ The following example sets actions for the 'c' and 'x' keys.
+ \qml
+ KeyActions { keyC: "print('c is for cookie')"; keyX: "print('I like cookies')" }
+ \endqml
+*/
+QString QFxKeyActions::key_A() const
+{
+ return d->keyExpr(Qt::Key_A);
+}
+
+void QFxKeyActions::setKey_A(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_A, s);
+}
+
+QString QFxKeyActions::key_B() const
+{
+ return d->keyExpr(Qt::Key_B);
+}
+
+void QFxKeyActions::setKey_B(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_B, s);
+}
+
+QString QFxKeyActions::key_C() const
+{
+ return d->keyExpr(Qt::Key_C);
+}
+
+void QFxKeyActions::setKey_C(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_C, s);
+}
+
+QString QFxKeyActions::key_D() const
+{
+ return d->keyExpr(Qt::Key_D);
+}
+
+void QFxKeyActions::setKey_D(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_D, s);
+}
+
+QString QFxKeyActions::key_E() const
+{
+ return d->keyExpr(Qt::Key_E);
+}
+
+void QFxKeyActions::setKey_E(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_E, s);
+}
+
+QString QFxKeyActions::key_F() const
+{
+ return d->keyExpr(Qt::Key_F);
+}
+
+void QFxKeyActions::setKey_F(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_F, s);
+}
+
+QString QFxKeyActions::key_G() const
+{
+ return d->keyExpr(Qt::Key_G);
+}
+
+void QFxKeyActions::setKey_G(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_G, s);
+}
+
+QString QFxKeyActions::key_H() const
+{
+ return d->keyExpr(Qt::Key_H);
+}
+
+void QFxKeyActions::setKey_H(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_H, s);
+}
+
+QString QFxKeyActions::key_I() const
+{
+ return d->keyExpr(Qt::Key_I);
+}
+
+void QFxKeyActions::setKey_I(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_I, s);
+}
+
+QString QFxKeyActions::key_J() const
+{
+ return d->keyExpr(Qt::Key_J);
+}
+
+void QFxKeyActions::setKey_J(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_J, s);
+}
+
+QString QFxKeyActions::key_K() const
+{
+ return d->keyExpr(Qt::Key_K);
+}
+
+void QFxKeyActions::setKey_K(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_K, s);
+}
+
+QString QFxKeyActions::key_L() const
+{
+ return d->keyExpr(Qt::Key_L);
+}
+
+void QFxKeyActions::setKey_L(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_L, s);
+}
+
+QString QFxKeyActions::key_M() const
+{
+ return d->keyExpr(Qt::Key_M);
+}
+
+void QFxKeyActions::setKey_M(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_M, s);
+}
+
+QString QFxKeyActions::key_N() const
+{
+ return d->keyExpr(Qt::Key_N);
+}
+
+void QFxKeyActions::setKey_N(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_N, s);
+}
+
+QString QFxKeyActions::key_O() const
+{
+ return d->keyExpr(Qt::Key_O);
+}
+
+void QFxKeyActions::setKey_O(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_O, s);
+}
+
+QString QFxKeyActions::key_P() const
+{
+ return d->keyExpr(Qt::Key_P);
+}
+
+void QFxKeyActions::setKey_P(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_P, s);
+}
+
+QString QFxKeyActions::key_Q() const
+{
+ return d->keyExpr(Qt::Key_Q);
+}
+
+void QFxKeyActions::setKey_Q(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Q, s);
+}
+
+QString QFxKeyActions::key_R() const
+{
+ return d->keyExpr(Qt::Key_R);
+}
+
+void QFxKeyActions::setKey_R(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_R, s);
+}
+
+QString QFxKeyActions::key_S() const
+{
+ return d->keyExpr(Qt::Key_S);
+}
+
+void QFxKeyActions::setKey_S(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_S, s);
+}
+
+QString QFxKeyActions::key_T() const
+{
+ return d->keyExpr(Qt::Key_T);
+}
+
+void QFxKeyActions::setKey_T(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_T, s);
+}
+
+QString QFxKeyActions::key_U() const
+{
+ return d->keyExpr(Qt::Key_U);
+}
+
+void QFxKeyActions::setKey_U(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_U, s);
+}
+
+QString QFxKeyActions::key_V() const
+{
+ return d->keyExpr(Qt::Key_V);
+}
+
+void QFxKeyActions::setKey_V(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_V, s);
+}
+
+QString QFxKeyActions::key_W() const
+{
+ return d->keyExpr(Qt::Key_W);
+}
+
+void QFxKeyActions::setKey_W(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_W, s);
+}
+
+QString QFxKeyActions::key_X() const
+{
+ return d->keyExpr(Qt::Key_X);
+}
+
+void QFxKeyActions::setKey_X(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_X, s);
+}
+
+QString QFxKeyActions::key_Y() const
+{
+ return d->keyExpr(Qt::Key_Y);
+}
+
+void QFxKeyActions::setKey_Y(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Y, s);
+}
+
+QString QFxKeyActions::key_Z() const
+{
+ return d->keyExpr(Qt::Key_Z);
+}
+
+void QFxKeyActions::setKey_Z(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Z, s);
+}
+
+
+/*!
+ \qmlproperty string KeyActions::leftArrow
+ \qmlproperty string KeyActions::rightArrow
+ \qmlproperty string KeyActions::upArrow
+ \qmlproperty string KeyActions::downArrow
+
+ The action to take for the given arrow key.
+
+ The following example sets actions for the left and right arrow keys.
+ \qml
+ KeyActions { leftArrow: "print('You pressed left')"; rightArrow: "print('You pressed right')" }
+ \endqml
+*/
+
+QString QFxKeyActions::key_Left() const
+{
+ return d->keyExpr(Qt::Key_Left);
+}
+
+void QFxKeyActions::setKey_Left(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Left, s);
+}
+
+QString QFxKeyActions::key_Right() const
+{
+ return d->keyExpr(Qt::Key_Right);
+}
+
+void QFxKeyActions::setKey_Right(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Right, s);
+}
+
+QString QFxKeyActions::key_Up() const
+{
+ return d->keyExpr(Qt::Key_Up);
+}
+
+void QFxKeyActions::setKey_Up(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Up, s);
+}
+
+QString QFxKeyActions::key_Down() const
+{
+ return d->keyExpr(Qt::Key_Down);
+}
+
+void QFxKeyActions::setKey_Down(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Down, s);
+}
+
+/*!
+ \qmlproperty string KeyActions::digit0...digit9
+
+ The action to take for the given number key.
+
+ The following example sets actions for the '5' and '6' keys.
+ \qml
+ KeyActions { digit5: "print('5 is a prime number')"; digit6: "print('6 is a composite number')"; focus: true }
+ \endqml
+*/
+
+QString QFxKeyActions::key_0() const
+{
+ return d->keyExpr(Qt::Key_0);
+}
+
+void QFxKeyActions::setKey_0(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_0, s);
+}
+
+QString QFxKeyActions::key_1() const
+{
+ return d->keyExpr(Qt::Key_1);
+}
+
+void QFxKeyActions::setKey_1(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_1, s);
+}
+
+QString QFxKeyActions::key_2() const
+{
+ return d->keyExpr(Qt::Key_2);
+}
+
+void QFxKeyActions::setKey_2(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_2, s);
+}
+
+QString QFxKeyActions::key_3() const
+{
+ return d->keyExpr(Qt::Key_3);
+}
+
+void QFxKeyActions::setKey_3(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_3, s);
+}
+
+QString QFxKeyActions::key_4() const
+{
+ return d->keyExpr(Qt::Key_4);
+}
+
+void QFxKeyActions::setKey_4(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_4, s);
+}
+
+QString QFxKeyActions::key_5() const
+{
+ return d->keyExpr(Qt::Key_5);
+}
+
+void QFxKeyActions::setKey_5(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_5, s);
+}
+
+QString QFxKeyActions::key_6() const
+{
+ return d->keyExpr(Qt::Key_6);
+}
+
+void QFxKeyActions::setKey_6(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_6, s);
+}
+
+QString QFxKeyActions::key_7() const
+{
+ return d->keyExpr(Qt::Key_7);
+}
+
+void QFxKeyActions::setKey_7(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_7, s);
+}
+
+QString QFxKeyActions::key_8() const
+{
+ return d->keyExpr(Qt::Key_8);
+}
+
+void QFxKeyActions::setKey_8(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_8, s);
+}
+
+QString QFxKeyActions::key_9() const
+{
+ return d->keyExpr(Qt::Key_9);
+}
+
+void QFxKeyActions::setKey_9(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_9, s);
+}
+
+QString QFxKeyActions::key_Asterisk() const
+{
+ return d->keyExpr(Qt::Key_Asterisk);
+}
+
+void QFxKeyActions::setKey_Asterisk(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Asterisk, s);
+}
+
+QString QFxKeyActions::key_Escape() const
+{
+ return d->keyExpr(Qt::Key_Escape);
+}
+
+void QFxKeyActions::setKey_Escape(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Escape, s);
+}
+
+QString QFxKeyActions::key_Return() const
+{
+ return d->keyExpr(Qt::Key_Return);
+}
+
+void QFxKeyActions::setKey_Return(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Return, s);
+}
+
+QString QFxKeyActions::key_Enter() const
+{
+ return d->keyExpr(Qt::Key_Enter);
+}
+
+void QFxKeyActions::setKey_Enter(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Enter, s);
+}
+
+QString QFxKeyActions::key_Delete() const
+{
+ return d->keyExpr(Qt::Key_Delete);
+}
+
+void QFxKeyActions::setKey_Delete(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Delete, s);
+}
+
+QString QFxKeyActions::key_Space() const
+{
+ return d->keyExpr(Qt::Key_Space);
+}
+
+void QFxKeyActions::setKey_Space(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Space, s);
+}
+
+/*!
+ \qmlproperty string KeyActions::escape
+ \qmlproperty string KeyActions::keyReturn
+ \qmlproperty string KeyActions::enter
+ \qmlproperty string KeyActions::delete
+ \qmlproperty string KeyActions::space
+
+ The action to take for the given utility key.
+
+ The following example sets an action for the space key.
+ \qml
+ KeyActions { space: "print('Space pressed')" }
+ \endqml
+*/
+
+/*!
+ \qmlproperty string KeyActions::back
+ \qmlproperty string KeyActions::select
+ \qmlproperty string KeyActions::yes
+ \qmlproperty string KeyActions::no
+ \qmlproperty string KeyActions::context1
+ \qmlproperty string KeyActions::context2
+ \qmlproperty string KeyActions::context3
+ \qmlproperty string KeyActions::context4
+ \qmlproperty string KeyActions::call
+ \qmlproperty string KeyActions::hangup
+ \qmlproperty string KeyActions::flip
+
+ The action to take for the given device key.
+
+ The following example sets an action for the hangup key.
+ \qml
+ KeyActions { hangup: "print('Go away now')" }
+ \endqml
+*/
+
+QString QFxKeyActions::key_Back() const
+{
+ return d->keyExpr(Qt::Key_Back);
+}
+
+void QFxKeyActions::setKey_Back(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Back, s);
+}
+
+QString QFxKeyActions::key_Select() const
+{
+ return d->keyExpr(Qt::Key_Select);
+}
+
+void QFxKeyActions::setKey_Select(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Select, s);
+}
+
+QString QFxKeyActions::key_Yes() const
+{
+ return d->keyExpr(Qt::Key_Yes);
+}
+
+void QFxKeyActions::setKey_Yes(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Yes, s);
+}
+
+QString QFxKeyActions::key_No() const
+{
+ return d->keyExpr(Qt::Key_No);
+}
+
+void QFxKeyActions::setKey_No(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_No, s);
+}
+
+QString QFxKeyActions::key_Context1() const
+{
+ return d->keyExpr(Qt::Key_Context1);
+}
+
+void QFxKeyActions::setKey_Context1(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Context1, s);
+}
+
+QString QFxKeyActions::key_Context2() const
+{
+ return d->keyExpr(Qt::Key_Context2);
+}
+
+void QFxKeyActions::setKey_Context2(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Context2, s);
+}
+
+QString QFxKeyActions::key_Context3() const
+{
+ return d->keyExpr(Qt::Key_Context3);
+}
+
+void QFxKeyActions::setKey_Context3(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Context3, s);
+}
+
+QString QFxKeyActions::key_Context4() const
+{
+ return d->keyExpr(Qt::Key_Context4);
+}
+
+void QFxKeyActions::setKey_Context4(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Context4, s);
+}
+
+QString QFxKeyActions::key_Call() const
+{
+ return d->keyExpr(Qt::Key_Call);
+}
+
+void QFxKeyActions::setKey_Call(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Call, s);
+}
+
+QString QFxKeyActions::key_Hangup() const
+{
+ return d->keyExpr(Qt::Key_Hangup);
+}
+
+void QFxKeyActions::setKey_Hangup(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Hangup, s);
+}
+
+QString QFxKeyActions::key_Flip() const
+{
+ return d->keyExpr(Qt::Key_Flip);
+}
+
+void QFxKeyActions::setKey_Flip(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_Flip, s);
+}
+
+/*!
+ \qmlproperty string KeyActions::any
+
+ The action to take for any key not otherwise handled.
+*/
+QString QFxKeyActions::key_Any() const
+{
+ return d->keyExpr(Qt::Key_unknown);
+}
+
+void QFxKeyActions::setKey_Any(const QString &s)
+{
+ d->setKeyExpr(Qt::Key_unknown, s);
+}
+
+void QFxKeyActions::keyPressEvent(QKeyEvent *event)
+{
+ Qt::Key key = (Qt::Key)event->key();
+ if (d->enabled && d->key(key)) {
+ QmlExpression b(qmlContext(this), d->action(key), this, false);
+ b.value();
+ event->accept();
+ } else {
+ QFxItem::keyPressEvent(event);
+ }
+}
+
+void QFxKeyActions::keyReleaseEvent(QKeyEvent *event)
+{
+ Qt::Key key = (Qt::Key)event->key();
+ if (d->enabled && d->key(key)) {
+ event->accept();
+ } else {
+ QFxItem::keyReleaseEvent(event);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxkeyactions.h b/src/declarative/fx/qfxkeyactions.h
new file mode 100644
index 0000000..7ad323a
--- /dev/null
+++ b/src/declarative/fx/qfxkeyactions.h
@@ -0,0 +1,319 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXKEYACTIONS_H
+#define QFXKEYACTIONS_H
+
+#include <qfxglobal.h>
+#include <QObject>
+#include <qml.h>
+#include <qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxKeyActionsPrivate;
+class Q_DECLARATIVE_EXPORT QFxKeyActions : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(QString keyA READ key_A WRITE setKey_A)
+ Q_PROPERTY(QString keyB READ key_B WRITE setKey_B)
+ Q_PROPERTY(QString keyC READ key_C WRITE setKey_C)
+ Q_PROPERTY(QString keyD READ key_D WRITE setKey_D)
+ Q_PROPERTY(QString keyE READ key_E WRITE setKey_E)
+ Q_PROPERTY(QString keyF READ key_F WRITE setKey_F)
+ Q_PROPERTY(QString keyG READ key_G WRITE setKey_G)
+ Q_PROPERTY(QString keyH READ key_H WRITE setKey_H)
+ Q_PROPERTY(QString keyI READ key_I WRITE setKey_I)
+ Q_PROPERTY(QString keyJ READ key_J WRITE setKey_J)
+ Q_PROPERTY(QString keyK READ key_K WRITE setKey_K)
+ Q_PROPERTY(QString keyL READ key_L WRITE setKey_L)
+ Q_PROPERTY(QString keyM READ key_M WRITE setKey_M)
+ Q_PROPERTY(QString keyN READ key_N WRITE setKey_N)
+ Q_PROPERTY(QString keyO READ key_O WRITE setKey_O)
+ Q_PROPERTY(QString keyP READ key_P WRITE setKey_P)
+ Q_PROPERTY(QString keyQ READ key_Q WRITE setKey_Q)
+ Q_PROPERTY(QString keyR READ key_R WRITE setKey_R)
+ Q_PROPERTY(QString keyS READ key_S WRITE setKey_S)
+ Q_PROPERTY(QString keyT READ key_T WRITE setKey_T)
+ Q_PROPERTY(QString keyU READ key_U WRITE setKey_U)
+ Q_PROPERTY(QString keyV READ key_V WRITE setKey_V)
+ Q_PROPERTY(QString keyW READ key_W WRITE setKey_W)
+ Q_PROPERTY(QString keyX READ key_X WRITE setKey_X)
+ Q_PROPERTY(QString keyY READ key_Y WRITE setKey_Y)
+ Q_PROPERTY(QString keyZ READ key_Z WRITE setKey_Z)
+ Q_PROPERTY(QString leftArrow READ key_Left WRITE setKey_Left)
+ Q_PROPERTY(QString rightArrow READ key_Right WRITE setKey_Right)
+ Q_PROPERTY(QString upArrow READ key_Up WRITE setKey_Up)
+ Q_PROPERTY(QString downArrow READ key_Down WRITE setKey_Down)
+ Q_PROPERTY(QString digit0 READ key_0 WRITE setKey_0)
+ Q_PROPERTY(QString digit1 READ key_1 WRITE setKey_1)
+ Q_PROPERTY(QString digit2 READ key_2 WRITE setKey_2)
+ Q_PROPERTY(QString digit3 READ key_3 WRITE setKey_3)
+ Q_PROPERTY(QString digit4 READ key_4 WRITE setKey_4)
+ Q_PROPERTY(QString digit5 READ key_5 WRITE setKey_5)
+ Q_PROPERTY(QString digit6 READ key_6 WRITE setKey_6)
+ Q_PROPERTY(QString digit7 READ key_7 WRITE setKey_7)
+ Q_PROPERTY(QString digit8 READ key_8 WRITE setKey_8)
+ Q_PROPERTY(QString digit9 READ key_9 WRITE setKey_9)
+ Q_PROPERTY(QString asterisk READ key_Asterisk WRITE setKey_Asterisk)
+ Q_PROPERTY(QString escape READ key_Escape WRITE setKey_Escape)
+ Q_PROPERTY(QString return READ key_Return WRITE setKey_Return)
+ Q_PROPERTY(QString enter READ key_Enter WRITE setKey_Enter)
+ Q_PROPERTY(QString delete READ key_Delete WRITE setKey_Delete)
+ Q_PROPERTY(QString space READ key_Space WRITE setKey_Space)
+ Q_PROPERTY(QString back READ key_Back WRITE setKey_Back)
+ Q_PROPERTY(QString select READ key_Select WRITE setKey_Select)
+ Q_PROPERTY(QString yes READ key_Yes WRITE setKey_Yes)
+ Q_PROPERTY(QString no READ key_No WRITE setKey_No)
+ Q_PROPERTY(QString context1 READ key_Context1 WRITE setKey_Context1)
+ Q_PROPERTY(QString context2 READ key_Context2 WRITE setKey_Context2)
+ Q_PROPERTY(QString context3 READ key_Context3 WRITE setKey_Context3)
+ Q_PROPERTY(QString context4 READ key_Context4 WRITE setKey_Context4)
+ Q_PROPERTY(QString call READ key_Call WRITE setKey_Call)
+ Q_PROPERTY(QString hangup READ key_Hangup WRITE setKey_Hangup)
+ Q_PROPERTY(QString flip READ key_Flip WRITE setKey_Flip)
+ Q_PROPERTY(QString any READ key_Any WRITE setKey_Any)
+
+public:
+ QFxKeyActions(QFxItem *parent=0);
+ virtual ~QFxKeyActions();
+
+ bool enabled() const;
+ void setEnabled(bool);
+
+ QString key_A() const;
+ void setKey_A(const QString &);
+
+ QString key_B() const;
+ void setKey_B(const QString &);
+
+ QString key_C() const;
+ void setKey_C(const QString &);
+
+ QString key_D() const;
+ void setKey_D(const QString &);
+
+ QString key_E() const;
+ void setKey_E(const QString &);
+
+ QString key_F() const;
+ void setKey_F(const QString &);
+
+ QString key_G() const;
+ void setKey_G(const QString &);
+
+ QString key_H() const;
+ void setKey_H(const QString &);
+
+ QString key_I() const;
+ void setKey_I(const QString &);
+
+ QString key_J() const;
+ void setKey_J(const QString &);
+
+ QString key_K() const;
+ void setKey_K(const QString &);
+
+ QString key_L() const;
+ void setKey_L(const QString &);
+
+ QString key_M() const;
+ void setKey_M(const QString &);
+
+ QString key_N() const;
+ void setKey_N(const QString &);
+
+ QString key_O() const;
+ void setKey_O(const QString &);
+
+ QString key_P() const;
+ void setKey_P(const QString &);
+
+ QString key_Q() const;
+ void setKey_Q(const QString &);
+
+ QString key_R() const;
+ void setKey_R(const QString &);
+
+ QString key_S() const;
+ void setKey_S(const QString &);
+
+ QString key_T() const;
+ void setKey_T(const QString &);
+
+ QString key_U() const;
+ void setKey_U(const QString &);
+
+ QString key_V() const;
+ void setKey_V(const QString &);
+
+ QString key_W() const;
+ void setKey_W(const QString &);
+
+ QString key_X() const;
+ void setKey_X(const QString &);
+
+ QString key_Y() const;
+ void setKey_Y(const QString &);
+
+ QString key_Z() const;
+ void setKey_Z(const QString &);
+
+ QString key_Left() const;
+ void setKey_Left(const QString &);
+
+ QString key_Right() const;
+ void setKey_Right(const QString &);
+
+ QString key_Up() const;
+ void setKey_Up(const QString &);
+
+ QString key_Down() const;
+ void setKey_Down(const QString &);
+
+ QString key_0() const;
+ void setKey_0(const QString &);
+
+ QString key_1() const;
+ void setKey_1(const QString &);
+
+ QString key_2() const;
+ void setKey_2(const QString &);
+
+ QString key_3() const;
+ void setKey_3(const QString &);
+
+ QString key_4() const;
+ void setKey_4(const QString &);
+
+ QString key_5() const;
+ void setKey_5(const QString &);
+
+ QString key_6() const;
+ void setKey_6(const QString &);
+
+ QString key_7() const;
+ void setKey_7(const QString &);
+
+ QString key_8() const;
+ void setKey_8(const QString &);
+
+ QString key_9() const;
+ void setKey_9(const QString &);
+
+ QString key_Asterisk() const;
+ void setKey_Asterisk(const QString &);
+
+ QString key_Escape() const;
+ void setKey_Escape(const QString &);
+
+ QString key_Return() const;
+ void setKey_Return(const QString &);
+
+ QString key_Enter() const;
+ void setKey_Enter(const QString &);
+
+ QString key_Delete() const;
+ void setKey_Delete(const QString &);
+
+ QString key_Space() const;
+ void setKey_Space(const QString &);
+
+ QString key_Back() const;
+ void setKey_Back(const QString &);
+
+ QString key_Select() const;
+ void setKey_Select(const QString &);
+
+ QString key_Yes() const;
+ void setKey_Yes(const QString &);
+
+ QString key_No() const;
+ void setKey_No(const QString &);
+
+ QString key_Context1() const;
+ void setKey_Context1(const QString &);
+
+ QString key_Context2() const;
+ void setKey_Context2(const QString &);
+
+ QString key_Context3() const;
+ void setKey_Context3(const QString &);
+
+ QString key_Context4() const;
+ void setKey_Context4(const QString &);
+
+ QString key_Call() const;
+ void setKey_Call(const QString &);
+
+ QString key_Hangup() const;
+ void setKey_Hangup(const QString &);
+
+ QString key_Flip() const;
+ void setKey_Flip(const QString &);
+
+ QString key_Any() const;
+ void setKey_Any(const QString &);
+
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+
+Q_SIGNALS:
+ void enabledChanged();
+
+private:
+ Q_DISABLE_COPY(QFxKeyActions)
+ QFxKeyActionsPrivate *d;
+};
+
+QML_DECLARE_TYPE(QFxKeyActions);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXKEYACTIONS_H
diff --git a/src/declarative/fx/qfxkeyproxy.cpp b/src/declarative/fx/qfxkeyproxy.cpp
new file mode 100644
index 0000000..848b2d9
--- /dev/null
+++ b/src/declarative/fx/qfxkeyproxy.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxkeyproxy.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxKeyProxy,KeyProxy);
+
+/*!
+ \qmlclass KeyProxy
+ \brief The KeyProxy item proxies key presses to a number of other items.
+ \inherits Item
+
+*/
+
+/*!
+ \internal
+ \class QFxKeyProxy
+ \brief The QFxKeyProxy class proxies key presses to a number of other items.
+ \ingroup group_utility
+*/
+
+class QFxKeyProxyPrivate
+{
+public:
+ QList<QFxItem *> targets;
+};
+
+QFxKeyProxy::QFxKeyProxy(QFxItem *parent)
+: QFxItem(parent), d(new QFxKeyProxyPrivate)
+{
+}
+
+QFxKeyProxy::~QFxKeyProxy()
+{
+ delete d; d = 0;
+}
+
+/*!
+ \qmlproperty list<Item> KeyProxy::targets
+
+ The proxy targets.
+*/
+
+/*!
+ \property QFxKeyProxy::targets
+ \brief the proxy targets.
+*/
+
+QList<QFxItem *> *QFxKeyProxy::targets() const
+{
+ return &d->targets;
+}
+
+void QFxKeyProxy::keyPressEvent(QKeyEvent *e)
+{
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QSimpleCanvasItem *i = canvas()->focusItem(d->targets.at(ii));
+ if (i)
+ i->keyPressEvent(e);
+ if (e->isAccepted())
+ return;
+ }
+}
+
+void QFxKeyProxy::keyReleaseEvent(QKeyEvent *e)
+{
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QSimpleCanvasItem *i = canvas()->focusItem(d->targets.at(ii));
+ if (i)
+ i->keyReleaseEvent(e);
+ if (e->isAccepted())
+ return;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxkeyproxy.h b/src/declarative/fx/qfxkeyproxy.h
new file mode 100644
index 0000000..ae5fce4
--- /dev/null
+++ b/src/declarative/fx/qfxkeyproxy.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXKEYPROXY_H
+#define QFXKEYPROXY_H
+
+#include <qfxitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxKeyProxyPrivate;
+class Q_DECLARATIVE_EXPORT QFxKeyProxy : public QFxItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<QFxItem *> *targets READ targets)
+public:
+ QFxKeyProxy(QFxItem *parent=0);
+ virtual ~QFxKeyProxy();
+
+ QList<QFxItem *> *targets() const;
+
+protected:
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+
+private:
+ Q_DISABLE_COPY(QFxKeyProxy)
+ QFxKeyProxyPrivate *d;
+};
+
+QML_DECLARE_TYPE(QFxKeyProxy);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXKEYPROXY_H
diff --git a/src/declarative/fx/qfxlayouts.cpp b/src/declarative/fx/qfxlayouts.cpp
new file mode 100644
index 0000000..e95998b
--- /dev/null
+++ b/src/declarative/fx/qfxlayouts.cpp
@@ -0,0 +1,1082 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include <QCoreApplication>
+#include "qml.h"
+#include "qmlstate.h"
+#include "qmlstategroup.h"
+#include "qmlstateoperations.h"
+#include "qfxperf.h"
+#include "qfxlayouts.h"
+#include "qfxlayouts_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QFxBaseLayout
+ \brief The QFxBaseLayout class provides a base for QFx layouts.
+
+ To create a QFx Layout, simple subclass QFxBaseLayout and implement
+ doLayout(), which is automatically called when the layout might need
+ updating.
+
+ It is strongly recommended that in your implementation of doLayout()
+ that you use the move, remove and add transitions when those conditions
+ arise.
+
+ \ingroup group_layouts
+*/
+QFxBaseLayout::QFxBaseLayout(AutoUpdateType at, QFxItem *parent)
+ : QFxItem(*(new QFxBaseLayoutPrivate), parent)
+{
+ Q_D(QFxBaseLayout);
+ d->init(at);
+}
+
+QFxBaseLayout::QFxBaseLayout(QFxBaseLayoutPrivate &dd, AutoUpdateType at, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxBaseLayout);
+ d->init(at);
+}
+
+/*!
+ \property QFxBaseLayout::spacing
+ \brief the amount of spacing between items (in px)
+
+ Note that the subclass is repsonsible for ensuring this.
+*/
+int QFxBaseLayout::spacing() const
+{
+ Q_D(const QFxBaseLayout);
+ return d->_spacing;
+}
+
+void QFxBaseLayout::setSpacing(int s)
+{
+ Q_D(QFxBaseLayout);
+ if (s==d->_spacing)
+ return;
+ d->_spacing = s;
+ preLayout();
+}
+
+/*!
+ \property QFxBaseLayout::margin
+ \brief the size of the margin around all items (in px)
+
+*/
+int QFxBaseLayout::margin() const
+{
+ Q_D(const QFxBaseLayout);
+ return d->_margin;
+}
+
+void QFxBaseLayout::setMargin(int s)
+{
+ Q_D(QFxBaseLayout);
+ if (s==d->_margin)
+ return;
+ d->_margin = s;
+ preLayout();
+}
+
+
+/*!
+ \property QFxBaseLayout::move
+ \brief the transition when moving an item.
+
+ \qml
+BaseLayout {
+ id: layout
+ y: 0
+ move: Transition {
+ NumericAnimation {
+ properties: "y"
+ ease: "easeOutBounce"
+ }
+ }
+}
+ \endqml
+*/
+QmlTransition *QFxBaseLayout::move() const
+{
+ Q_D(const QFxBaseLayout);
+ return d->moveTransition;
+}
+
+void QFxBaseLayout::setMove(QmlTransition *mt)
+{
+ Q_D(QFxBaseLayout);
+ d->moveTransition = mt;
+}
+
+/*!
+ \property QFxBaseLayout::add
+ \brief the transition when adding an item.
+
+ \qml
+BaseLayout {
+ id: layout
+ y: 0
+ add: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 0
+ to: 1
+ duration: 500
+ }
+ }
+}
+ \endqml
+*/
+QmlTransition *QFxBaseLayout::add() const
+{
+ Q_D(const QFxBaseLayout);
+ return d->addTransition;
+}
+
+void QFxBaseLayout::setAdd(QmlTransition *add)
+{
+ Q_D(QFxBaseLayout);
+ d->addTransition = add;
+}
+
+
+/*!
+ \property QFxBaseLayout::remove
+ \brief the transition when removing an item.
+
+ Note that the item may be 'removed' because its opacity is zero. This can make certain
+ transitions difficult to see.
+ \qml
+BaseLayout {
+ id: layout
+ y: 0
+ remove: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 1
+ to: 0
+ duration: 500
+ }
+ }
+}
+ \endqml
+*/
+QmlTransition *QFxBaseLayout::remove() const
+{
+ Q_D(const QFxBaseLayout);
+ return d->removeTransition;
+}
+
+void QFxBaseLayout::setRemove(QmlTransition *remove)
+{
+ Q_D(QFxBaseLayout);
+ d->removeTransition = remove;
+}
+
+/*!
+ \property QFxBaseLayout::item
+
+ The item that is currently being laid out. Used to target transitions that apply
+ only to the item being laid out, such as in the add transition.
+*/
+
+QFxItem *QFxBaseLayout::layoutItem() const
+{
+ Q_D(const QFxBaseLayout);
+ return d->_layoutItem;
+}
+
+/*!
+ \internal
+*/
+void QFxBaseLayout::setLayoutItem(QFxItem *li)
+{
+ Q_D(QFxBaseLayout);
+ if (li == d->_layoutItem)
+ return;
+ d->_layoutItem = li;
+ emit layoutItemChanged();
+}
+
+void QFxBaseLayout::componentComplete()
+{
+ QFxItem::componentComplete();
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BaseLayoutComponentComplete> cc;
+#endif
+ preLayout();
+}
+
+void QFxBaseLayout::childrenChanged()
+{
+ preLayout();
+}
+
+bool QFxBaseLayout::event(QEvent *e)
+{
+ Q_D(QFxBaseLayout);
+ if (e->type() == QEvent::User) {
+ d->_ep = false;
+ d->_stableItems += d->_newItems;
+ d->_leavingItems.clear();
+ d->_newItems.clear();
+ return true;
+ }
+ return QFxItem::event(e);
+}
+
+/*!
+ Items that have just been added to the layout. This includes invisible items
+ that have turned visible.
+*/
+QSet<QFxItem *>* QFxBaseLayout::newItems()
+{
+ Q_D(QFxBaseLayout);
+ return &d->_newItems;
+}
+
+/*!
+ Items that are visible in the layout, not including ones that have just been added.
+*/
+QSet<QFxItem *>* QFxBaseLayout::items()
+{
+ Q_D(QFxBaseLayout);
+ return &d->_stableItems;
+}
+
+/*!
+ Items that have just left the layout. This includes visible items
+ that have turned invisible.
+*/
+QSet<QFxItem *>* QFxBaseLayout::leavingItems()
+{
+ Q_D(QFxBaseLayout);
+ return &d->_leavingItems;
+}
+
+void QFxBaseLayout::preLayout()
+{
+ Q_D(QFxBaseLayout);
+ if (!isComponentComplete() || d->_movingItem)
+ return;
+
+ if (!d->_ep) {
+ d->_ep = true;
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ }
+ if (d->stateGroup) {
+ delete d->stateGroup; d->stateGroup = 0;
+ }
+ QSet<QFxItem *> allItems;
+ for (int ii = 0; ii < this->QSimpleCanvasItem::children().count(); ++ii) {
+ QFxItem *child = qobject_cast<QFxItem *>(this->QSimpleCanvasItem::children().at(ii));
+ if (!child)
+ continue;
+ if (!d->_items.contains(child)){
+ QObject::connect(child, SIGNAL(visibleChanged()),
+ this, SLOT(preLayout()));
+ QObject::connect(child, SIGNAL(heightChanged()),
+ this, SLOT(preLayout()));
+ QObject::connect(child, SIGNAL(widthChanged()),
+ this, SLOT(preLayout()));
+ d->_items += child;
+ }
+ if (!child->isVisible()){
+ if (d->_stableItems.contains(child)){
+ d->_leavingItems += child;
+ d->_stableItems -= child;
+ }
+ }else if (!d->_stableItems.contains(child)){
+ d->_newItems+=child;
+ }
+ allItems += child;
+ }
+ QSet<QFxItem *> deletedItems = d->_items - allItems;
+ foreach(QFxItem *child, d->_items){
+ if (!allItems.contains(child)){
+ if (!deletedItems.contains(child)) {
+ QObject::disconnect(child, SIGNAL(visibleChanged()),
+ this, SLOT(preLayout()));
+ QObject::disconnect(child, SIGNAL(heightChanged()),
+ this, SLOT(preLayout()));
+ QObject::disconnect(child, SIGNAL(widthChanged()),
+ this, SLOT(preLayout()));
+ }
+ d->_items -= child;
+ }
+ }
+ d->_animated.clear();
+ doLayout();
+ //Set the layout's size to be the rect containing all children
+ //Also set the margin
+ qreal width=0;
+ qreal height=0;
+ foreach(QFxItem *item, d->_items){
+ if (item->isVisible()){
+ if (!d->_animated.contains(item)){
+ setMovingItem(item);
+ QPointF p(item->x(), item->y());
+ if(d->aut & Horizontal)
+ p.setX(p.x() + d->_margin);
+ if(d->aut & Vertical)
+ p.setY(p.y() + d->_margin);
+ item->setPos(p);
+ setMovingItem(0);
+ }
+ width = qMax(width, item->x() + item->width());
+ height = qMax(height, item->y() + item->height());
+ }
+ }
+ width += d->_margin;
+ height+= d->_margin;
+
+ if (d->aut & Horizontal)
+ setWidth(int(width));
+ else
+ setImplicitWidth(itemParent()->width());
+ if (d->aut & Vertical)
+ setHeight(int(height));
+ else
+ setImplicitHeight(itemParent()->height());
+ setLayoutItem(0);
+}
+
+//###This should be considered to move more centrally, as it seems useful
+void QFxBaseLayout::applyTransition(const QList<QPair<QString, QVariant> >& changes,
+ QFxItem* target, QmlTransition* trans)
+{
+ Q_D(QFxBaseLayout);
+ if (!trans||!target)//TODO: if !trans, just apply changes
+ return;
+ setLayoutItem(target);
+ if (d->stateGroup)
+ delete d->stateGroup;
+ d->stateGroup = new QmlStateGroup(this);
+
+ QmlState *state = new QmlState;
+ *(d->stateGroup->statesProperty()) << state;
+ for (int ii=0; ii<changes.size(); ++ii){
+ QmlSetProperty *sp = new QmlSetProperty(state);
+ sp->setObject(target);
+ QVariant val = changes[ii].second;
+ if (d->_margin &&
+ (changes[ii].first == QLatin1String("x") || changes[ii].first == QLatin1String("y"))){
+ val = QVariant(val.toInt() + d->_margin);
+ }
+ sp->setValue(val);
+ sp->setProperty(changes[ii].first);
+ *state << sp;
+ }
+ state->apply(d->stateGroup, trans, 0);
+ d->_animated << target;
+}
+
+void QFxBaseLayout::setMovingItem(QFxItem *i)
+{
+ Q_D(QFxBaseLayout);
+ d->_movingItem = i;
+}
+
+/*!
+ Applies the layout's add transition to the \a target item.\a changes is a list of property,value
+ pairs which will be changed on the target using the add transition.
+*/
+void QFxBaseLayout::applyAdd(const QList<QPair<QString, QVariant> >& changes, QFxItem* target)
+{
+ applyTransition(changes,target, add());
+}
+
+/*!
+ Applies the layout's move transition to the \a target.\a changes is a list of property,value pairs
+ which will be changed on the target using the move transition.
+*/
+void QFxBaseLayout::applyMove(const QList<QPair<QString, QVariant> >& changes, QFxItem* target)
+{
+ applyTransition(changes,target, move());
+}
+
+/*!
+ Applies the layout's remove transition to the \a target item.\a changes is a list of
+ property,value pairs which will be changed on the target using the remove transition.
+*/
+void QFxBaseLayout::applyRemove(const QList<QPair<QString, QVariant> >& changes, QFxItem* target)
+{
+ applyTransition(changes,target, remove());
+}
+
+QML_DEFINE_TYPE(QFxVerticalLayout, VerticalLayout);
+/*!
+ \qmlclass VerticalLayout
+ \brief The VerticalLayout item arranges its children in a vertical layout.
+ \inherits Item
+
+ The VerticalLayout item arranges its child items so that they are vertically
+ aligned and not overlapping. Spacing between items can be added, as can a margin around all the items.
+
+ The below example lays out differently shaped rectangles using a VerticalLayout.
+ \table
+ \row
+ \o \image verticalLayout_example.png
+ \o
+ \qml
+VerticalLayout {
+ spacing: 2
+ Rect { color: "red"; width: 50; height: 50 }
+ Rect { color: "green"; width: 20; height: 50 }
+ Rect { color: "blue"; width: 50; height: 20 }
+}
+ \endqml
+ \endtable
+
+ VerticalLayout also provides for transitions to be set when items are added, moved,
+ or removed in the layout. Adding and removing apply both to items which are deleted
+ or have their position in the document changed so as to no longer be children of the layout,
+ as well as to items which have their opacity set to or from zero so as to appear or disappear.
+
+ \table
+ \row
+ \o \image verticalLayout_transition.gif
+ \o
+ \qml
+VerticalLayout {
+ spacing: 2
+ remove: ...
+ add: ...
+ move: ...
+ ...
+}
+ \endqml
+ \endtable
+
+
+*/
+/*!
+ \qmlproperty Transition VerticalLayout::remove
+ This property holds the transition to apply when removing an item from the layout.
+
+ Removed can mean that either the object has been deleted or reparented, and thus is now longer a child of the layout, or that the object has had its opacity set to zero, and thus is no longer visible.
+
+ Note that if the item counts as removed because its opacity is zero it will not be visible during the transition unless you set the opacity in the transition, like in the below example.
+
+ \table
+ \row
+ \o \image layout-remove.gif
+ \o
+ \qml
+VerticalLayout {
+ id: layout
+ remove: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 1
+ to: 0
+ duration: 500
+ }
+ }
+}
+ \endqml
+ \endtable
+
+*/
+/*!
+ \qmlproperty Transition VerticalLayout::add
+ This property holds the transition to be applied when adding an item to the layout.
+
+ Added can mean that either the object has been created or reparented, and thus is now a child or the layout, or that the object has had its opacity increased from zero, and thus is now visible.
+
+ \table
+ \row
+ \o \image layout-add.gif
+ \o
+ \qml
+VerticalLayout {
+ id: layout
+ add: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 0
+ to: 1
+ duration: 500
+ }
+ }
+}
+ \endqml
+ \endtable
+
+*/
+/*!
+ \qmlproperty Transition VerticalLayout::move
+ This property holds the transition to apply when moving an item within the layout.
+
+ This can happen when other items are added or removed from the layout, or when items resize themselves.
+
+ \table
+ \row
+ \o \image layout-move.gif
+ \o
+ \qml
+VerticalLayout {
+ id: layout
+ move: Transition {
+ NumericAnimation {
+ properties: "y"
+ ease: "easeOutBounce"
+ }
+ }
+}
+ \endqml
+ \endtable
+*/
+/*!
+ \qmlproperty Item VerticalLayout::item
+
+ The item that is currently being laid out. Used to target transitions that apply
+ only to the item being laid out, such as in the add transition.
+
+*/
+/*!
+ \qmlproperty int VerticalLayout::spacing
+ \qmlproperty int VerticalLayout::margin
+
+ spacing and margin allow you to control the empty space surrounding
+ items in layouts.
+
+ spacing is the amount in pixels left empty between each adjacent
+ item. margin is the amount in pixels which will be left empty
+ around the inside edge of the layout. Both default to 0.
+
+ The below example places a GridLayout containing a red, a blue and a
+ green rectangle on a gray background. The area the grid layout
+ occupies is colored white. The top layout has a spacing of 2 and a
+ margin of 5, the bottom layout has the defaults of no margin or
+ spacing.
+
+ \image spacing_a.png
+ \image spacing_b.png
+
+*/
+/*!
+ \internal
+ \class QFxVerticalLayout
+ \brief The QFxVerticalLayout class lines up items vertically.
+ \ingroup group_layouts
+*/
+QFxVerticalLayout::QFxVerticalLayout(QFxItem *parent)
+: QFxBaseLayout(Vertical, parent)
+{
+}
+
+void QFxVerticalLayout::doLayout()
+{
+ int voffset = 0;
+
+ foreach(QFxItem* item, *leavingItems()){
+ if (remove()){
+ QList<QPair<QString,QVariant> > changes;
+ applyRemove(changes, item);
+ }
+ }
+ for (int ii = 0; ii < this->QSimpleCanvasItem::children().count(); ++ii) {
+ QFxItem *child = qobject_cast<QFxItem *>(this->QSimpleCanvasItem::children().at(ii));
+ if (!child || !child->isVisible())
+ continue;
+
+ bool needMove = (child->y() != voffset || child->x());
+
+ QList<QPair<QString, QVariant> > changes;
+ changes << qMakePair(QString(QLatin1String("y")),QVariant(voffset));
+ changes << qMakePair(QString(QLatin1String("x")),QVariant(0));
+ if (needMove && items()->contains(child) && move()) {
+ applyMove(changes,child);
+ } else if (!items()->contains(child) && add()) {
+ applyAdd(changes,child);
+ } else if (needMove) {
+ setMovingItem(child);
+ child->setY(voffset);
+ setMovingItem(0);
+ }
+ voffset += child->height();
+ voffset += spacing();
+ }
+ setMovingItem(this);
+ setHeight(voffset);
+ setMovingItem(0);
+}
+
+QML_DEFINE_TYPE(QFxHorizontalLayout,HorizontalLayout);
+/*!
+ \qmlclass HorizontalLayout
+ \brief The HorizontalLayout item arranges its children in a horizontal layout.
+ \inherits Item
+
+ The HorizontalLayout item arranges its child items so that they are horizontally aligned and not overlapping. Spacing can be added between the items, and a margin around all items can also be added. It also provides for transitions to be set when items are added, moved, or removed in the layout. Adding and removing apply both to items which are deleted or have their position in the document changed so as to no longer be children of the layout, as well as to items which have their opacity set to or from zero so as to appear or disappear.
+
+ The below example lays out differently shaped rectangles using a HorizontalLayout.
+ \qml
+HorizontalLayout {
+ spacing: 2
+ Rect { color: "red"; width: 50; height: 50 }
+ Rect { color: "green"; width: 20; height: 50 }
+ Rect { color: "blue"; width: 50; height: 20 }
+}
+ \endqml
+ \image horizontalLayout_example.png
+
+*/
+/*!
+ \qmlproperty Transition HorizontalLayout::remove
+ This property holds the transition to apply when removing an item from the layout.
+
+ Removed can mean that either the object has been deleted or reparented, and thus is now longer a child of the layout, or that the object has had its opacity set to zero, and thus is no longer visible.
+
+ Note that if the item counts as removed because its opacity is zero it will not be visible during the transition unless you set the opacity in the transition, like in the below example.
+
+ \qml
+HorizontalLayout {
+ id: layout
+ remove: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 1
+ to: 0
+ duration: 500
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty Transition HorizontalLayout::add
+ This property holds the transition to apply when adding an item to the layout.
+
+ Added can mean that either the object has been created or reparented, and thus is now a child or the layout, or that the object has had its opacity increased from zero, and thus is now visible.
+
+ \qml
+HorizontalLayout {
+ id: layout
+ add: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 0
+ to: 1
+ duration: 500
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty Transition HorizontalLayout::move
+ This property holds the transition to apply when moving an item within the layout.
+
+ This can happen when other items are added or removed from the layout, or when items resize themselves.
+
+ \qml
+HorizontalLayout {
+ id: layout
+ move: Transition {
+ NumericAnimation {
+ properties: "x"
+ ease: "easeOutBounce"
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty Item HorizontalLayout::item
+
+ The item that is currently being laid out. Used to target transitions that apply
+ only to the item being laid out, such as in the add transition.
+
+*/
+/*!
+ \qmlproperty int HorizontalLayout::spacing
+
+ The spacing, in pixels, left empty between each adjacent item.
+*/
+/*!
+ \qmlproperty int HorizontalLayout::margin
+
+ The margin size, in pixels, which will be left empty around the inside edge of the layout.
+*/
+/*!
+ \qmlproperty int HorizontalLayout::spacing
+ \qmlproperty int HorizontalLayout::margin
+
+ spacing and margin allow you to control the empty space surrounding items in layouts.
+
+ spacing is the amount in pixels left empty between each adjacent item.
+ margin is the amount in pixels which will be left empty around the inside edge of the layout.
+ Both default to 0.
+
+ The below example places a GridLayout containing a red, a blue and a green rectangle on a gray background. The area the grid layout occupies is colored white. The top layout has a spacing of 2 and a margin of 5, the bottom layout has the defaults of no margin or spacing.
+
+ \image spacing_a.png
+ \image spacing_b.png
+
+*/
+/*!
+ \internal
+ \class QFxHorizontalLayout
+ \brief The QFxHorizontalLayout class lines up items horizontally.
+ \ingroup group_layouts
+*/
+QFxHorizontalLayout::QFxHorizontalLayout(QFxItem *parent)
+: QFxBaseLayout(Horizontal, parent)
+{
+}
+
+void QFxHorizontalLayout::doLayout()
+{
+ int hoffset = 0;
+
+ foreach(QFxItem* item, *leavingItems()){
+ if (remove()){
+ QList<QPair<QString,QVariant> > changes;
+ applyRemove(changes, item);
+ }
+ }
+ for (int ii = 0; ii < this->QSimpleCanvasItem::children().count(); ++ii) {
+ QFxItem *child = qobject_cast<QFxItem *>(this->QSimpleCanvasItem::children().at(ii));
+ if (!child || !child->isVisible())
+ continue;
+
+ bool needMove = (child->x() != hoffset || child->y());
+
+ QList<QPair<QString, QVariant> > changes;
+ changes << qMakePair(QString(QLatin1String("x")),QVariant(hoffset));
+ changes << qMakePair(QString(QLatin1String("y")),QVariant(0));
+ if (needMove && items()->contains(child) && move()) {
+ applyMove(changes,child);
+ } else if (!items()->contains(child) && add()) {
+ applyAdd(changes,child);
+ } else if (needMove) {
+ setMovingItem(child);
+ child->setX(hoffset);
+ setMovingItem(0);
+ }
+ hoffset += child->width();
+ hoffset += spacing();
+ }
+ setWidth(hoffset);
+}
+
+QML_DEFINE_TYPE(QFxGridLayout,GridLayout);
+
+/*!
+ \qmlclass GridLayout QFxGridLayout
+ \brief The GridLayout item arranges its children in a grid layout.
+ \inherits Item
+
+ The GridLayout item arranges its child items so that they are
+ aligned in a grid and are not overlapping. Spacing can be added
+ between the items, and a margin around all the items can also be
+ defined. It also provides for transitions to be set when items are
+ added, moved, or removed in the layout. Adding and removing apply
+ both to items which are deleted or have their position in the
+ document changed so as to no longer be children of the layout, as
+ well as to items which have their opacity set to or from zero so
+ as to appear or disappear.
+
+ The GridLayout defaults to using four columns, and as many rows as
+ are necessary to fit all the child items. The number of rows
+ and/or the number of columns can be constrained by setting the rows
+ or columns properties. The grid layout calculates a grid with
+ rectangular cells of sufficient size to hold all items, and then
+ places the items in the cells, going across then down, and
+ positioning each item at the (0,0) corner of the cell. The below
+ example demonstrates this.
+
+ \table
+ \row
+ \o \image gridLayout_example.png
+ \o
+ \qml
+GridLayout {
+ columns: 3
+ spacing: 2
+ Rect { color: "red"; width: 50; height: 50 }
+ Rect { color: "green"; width: 20; height: 50 }
+ Rect { color: "blue"; width: 50; height: 20 }
+ Rect { color: "cyan"; width: 50; height: 50 }
+ Rect { color: "magenta"; width: 10; height: 10 }
+}
+ \endqml
+ \endtable
+*/
+/*!
+ \qmlproperty Transition GridLayout::remove
+ This property holds the transition to apply when removing an item from the layout.
+
+ Removed can mean that either the object has been deleted or
+ reparented, and thus is now longer a child of the layout, or that
+ the object has had its opacity set to zero, and thus is no longer
+ visible.
+
+ Note that if the item counts as removed because its opacity is
+ zero it will not be visible during the transition unless you set
+ the opacity in the transition, like in the below example.
+
+ \qml
+GridLayout {
+ id: layout
+ remove: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 1
+ to: 0
+ duration: 500
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty Transition GridLayout::add
+ This property holds the transition to apply when adding an item to the layout.
+
+ Added can mean that either the object has been created or
+ reparented, and thus is now a child or the layout, or that the
+ object has had its opacity increased from zero, and thus is now
+ visible.
+
+ \qml
+GridLayout {
+ id: layout
+ add: Transition {
+ NumericAnimation {
+ target: layout.item
+ properties: "opacity"
+ from: 0
+ to: 1
+ duration: 500
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty Transition GridLayout::move
+ This property holds the transition to apply when moving an item within the layout.
+
+ This can happen when other items are added or removed from the layout, or
+ when items resize themselves.
+
+ \qml
+GridLayout {
+ id: layout
+ move: Transition {
+ NumericAnimation {
+ properties: "x,y"
+ ease: "easeOutBounce"
+ }
+ }
+}
+ \endqml
+
+*/
+/*!
+ \qmlproperty Item GridLayout::item
+
+ The item that is currently being laid out. Used to target
+ transitions that apply only to the item being laid out, such as in
+ the add transition.
+
+*/
+/*!
+ \qmlproperty int GridLayout::spacing
+ \qmlproperty int GridLayout::margin
+
+ spacing and margin allow you to control the empty space surrounding
+ items in layouts.
+
+ spacing is the amount in pixels left empty between each adjacent
+ item. margin is the amount in pixels which will be left empty
+ around the inside edge of the layout. Both default to 0.
+
+ The below example places a GridLayout containing a red, a blue and a
+ green rectangle on a gray background. The area the grid layout
+ occupies is colored white. The top layout has a spacing of 2 and a
+ margin of 5, the bottom layout has the defaults of no margin or
+ spacing.
+
+ \image spacing_a.png
+ \image spacing_b.png
+
+*/
+/*!
+ \internal
+ \class QFxGridLayout
+ \brief The QFxGridLayout class lays out items in a grid.
+ \ingroup group_layouts
+
+*/
+QFxGridLayout::QFxGridLayout(QFxItem *parent) :
+ QFxBaseLayout(Both, parent)
+{
+ _columns=-1;
+ _rows=-1;
+}
+
+/*!
+ \qmlproperty int GridLayout::columns
+ This property holds the number of columns in the grid.
+
+ When the columns property is set the GridLayout will always have
+ that many columns. Note that if you do not have enough items to
+ fill this many columns some columns will be of zero width.
+*/
+
+/*!
+ \qmlproperty int GridLayout::rows
+ This property holds the number of rows in the grid.
+
+ When the rows property is set the GridLayout will always have that
+ many rows. Note that if you do not have enough items to fill this
+ many rows some rows will be of zero width.
+*/
+
+/*!
+ \property QFxGridLayout::columns
+ \brief the number of columns in the grid.
+*/
+
+/*!
+ \property QFxGridLayout::rows
+ \brief the number of rows in the grid.
+*/
+
+void QFxGridLayout::doLayout()
+{
+ int c=_columns,r=_rows;//Actual number of rows/columns
+ int numVisible = items()->size() + newItems()->size();
+ if (_columns==-1 && _rows==-1){
+ c = 4;
+ r = (numVisible+2)/3;
+ }else if (_rows==-1){
+ r = (numVisible+(_columns-1))/_columns;
+ }else if (_columns==-1){
+ c = (numVisible+(_rows-1))/_rows;
+ }
+
+ QList<int> maxColWidth;
+ QList<int> maxRowHeight;
+ int childIndex =0;
+ for (int i=0; i<r; i++){
+ for (int j=0; j<c; j++){
+ if (j==0)
+ maxRowHeight << 0;
+ if (i==0)
+ maxColWidth << 0;
+ if (childIndex == this->QSimpleCanvasItem::children().count())
+ continue;
+ QFxItem *child = qobject_cast<QFxItem *>(this->QSimpleCanvasItem::children().at(childIndex++));
+ if (!child || !child->isVisible())
+ continue;
+ if (child->width() > maxColWidth[j])
+ maxColWidth[j] = child->width();
+ if (child->height() > maxRowHeight[i])
+ maxRowHeight[i] = child->height();
+ }
+ }
+
+ int xoffset=0;
+ int yoffset=0;
+ int curRow =0;
+ int curCol =0;
+ foreach(QFxItem* item, *leavingItems()){
+ if (remove()){
+ QList<QPair<QString,QVariant> > changes;
+ applyRemove(changes, item);
+ }
+ }
+ foreach(QSimpleCanvasItem* schild, this->QSimpleCanvasItem::children()){
+ QFxItem *child = qobject_cast<QFxItem *>(schild);
+ if (!child || !child->isVisible())
+ continue;
+ bool needMove = (child->x()!=xoffset)||(child->y()!=yoffset);
+ QList<QPair<QString, QVariant> > changes;
+ changes << qMakePair(QString(QLatin1String("x")),QVariant(xoffset));
+ changes << qMakePair(QString(QLatin1String("y")),QVariant(yoffset));
+ if (newItems()->contains(child) && add()) {
+ applyAdd(changes,child);
+ } else if (needMove) {
+ if (move()){
+ applyMove(changes,child);
+ }else{
+ setMovingItem(child);
+ child->setPos(QPointF(xoffset, yoffset));
+ setMovingItem(0);
+ }
+ }
+ xoffset+=maxColWidth[curCol]+spacing();
+ curCol++;
+ curCol%=c;
+ if (!curCol){
+ yoffset+=maxRowHeight[curRow]+spacing();
+ xoffset=0;
+ curRow++;
+ if (curRow>=r)
+ return;
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxlayouts.h b/src/declarative/fx/qfxlayouts.h
new file mode 100644
index 0000000..acfc0c4
--- /dev/null
+++ b/src/declarative/fx/qfxlayouts.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXLAYOUTS_H
+#define QFXLAYOUTS_H
+
+#include <qfxitem.h>
+#include <QObject>
+#include <QString>
+#include <qmlstate.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxBaseLayoutPrivate;
+
+class Q_DECLARATIVE_EXPORT QFxBaseLayout : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int spacing READ spacing WRITE setSpacing)
+ Q_PROPERTY(int margin READ margin WRITE setMargin)
+ Q_PROPERTY(QmlTransition *move READ move WRITE setMove)
+ Q_PROPERTY(QmlTransition *add READ add WRITE setAdd)
+ Q_PROPERTY(QmlTransition *remove READ remove WRITE setRemove)
+ Q_PROPERTY(QFxItem *item READ layoutItem NOTIFY layoutItemChanged)
+public:
+ enum AutoUpdateType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 };
+ QFxBaseLayout(AutoUpdateType, QFxItem *parent);
+
+ int spacing() const;
+ void setSpacing(int);
+
+ int margin() const;
+ void setMargin(int);
+
+ QmlTransition *move() const;
+ void setMove(QmlTransition *);
+
+ QmlTransition *add() const;
+ void setAdd(QmlTransition *);
+
+ QmlTransition *remove() const;
+ void setRemove(QmlTransition *);
+
+ QFxItem *layoutItem() const;
+
+protected:
+ virtual void componentComplete();
+ virtual void childrenChanged();
+ virtual bool event(QEvent *);
+ QSet<QFxItem *>* newItems();
+ QSet<QFxItem *>* leavingItems();
+ QSet<QFxItem *>* items();
+ void applyAdd(const QList<QPair<QString, QVariant> >& changes, QFxItem* target);
+ void applyMove(const QList<QPair<QString, QVariant> >& changes, QFxItem* target);
+ void applyRemove(const QList<QPair<QString, QVariant> >& changes, QFxItem* target);
+
+Q_SIGNALS:
+ void layoutItemChanged();
+
+protected Q_SLOTS:
+ virtual void doLayout()=0;
+ void setLayoutItem(QFxItem *);
+
+private Q_SLOTS:
+ void preLayout();
+
+protected:
+ QFxBaseLayout(QFxBaseLayoutPrivate &dd, AutoUpdateType at, QFxItem *parent);
+ void setMovingItem(QFxItem *);
+
+private:
+ void applyTransition(const QList<QPair<QString, QVariant> >& changes, QFxItem* target,
+ QmlTransition* transition);
+ Q_DISABLE_COPY(QFxBaseLayout)
+ Q_DECLARE_PRIVATE(QFxBaseLayout)
+};
+
+class Q_DECLARATIVE_EXPORT QFxVerticalLayout : public QFxBaseLayout
+{
+ Q_OBJECT
+public:
+ QFxVerticalLayout(QFxItem *parent=0);
+protected Q_SLOTS:
+ virtual void doLayout();
+private:
+ Q_DISABLE_COPY(QFxVerticalLayout)
+};
+QML_DECLARE_TYPE(QFxVerticalLayout);
+
+class Q_DECLARATIVE_EXPORT QFxHorizontalLayout: public QFxBaseLayout
+{
+ Q_OBJECT
+public:
+ QFxHorizontalLayout(QFxItem *parent=0);
+protected Q_SLOTS:
+ virtual void doLayout();
+private:
+ Q_DISABLE_COPY(QFxHorizontalLayout)
+};
+QML_DECLARE_TYPE(QFxHorizontalLayout);
+
+class Q_DECLARATIVE_EXPORT QFxGridLayout : public QFxBaseLayout
+{
+ Q_OBJECT
+ Q_PROPERTY(int rows READ rows WRITE setRows)
+ Q_PROPERTY(int columns READ columns WRITE setcolumns)
+public:
+ QFxGridLayout(QFxItem *parent=0);
+
+ int rows() const {return _rows;}
+ void setRows(const int rows){_rows = rows;}
+
+ int columns() const {return _columns;}
+ void setcolumns(const int columns){_columns = columns;}
+protected Q_SLOTS:
+ virtual void doLayout();
+
+private:
+ int _rows;
+ int _columns;
+ Q_DISABLE_COPY(QFxGridLayout)
+};
+QML_DECLARE_TYPE(QFxGridLayout);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxlayouts_p.h b/src/declarative/fx/qfxlayouts_p.h
new file mode 100644
index 0000000..859482f
--- /dev/null
+++ b/src/declarative/fx/qfxlayouts_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXLAYOUTS_P_H
+#define QFXLAYOUTS_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 "qfxlayouts.h"
+#include "qfxitem_p.h"
+#include <QObject>
+#include <QString>
+#include <qmlstate.h>
+
+
+QT_BEGIN_NAMESPACE
+class QFxBaseLayoutPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxBaseLayout)
+
+public:
+ QFxBaseLayoutPrivate()
+ : _ep(false), _componentComplete(false), _spacing(0),
+ _margin(0), aut(QFxBaseLayout::None), moveTransition(0), addTransition(0),
+ removeTransition(0), _layoutItem(0), stateGroup(0), _movingItem(0)
+ {
+ }
+
+ void init(QFxBaseLayout::AutoUpdateType at)
+ {
+ aut = at;
+ }
+
+ bool _ep;
+ bool _componentComplete;
+ int _spacing;
+ int _margin;
+ QFxBaseLayout::AutoUpdateType aut;
+ QmlTransition *moveTransition;
+ QmlTransition *addTransition;
+ QmlTransition *removeTransition;
+ QSet<QFxItem *> _items;
+ QSet<QFxItem *> _leavingItems;
+ QSet<QFxItem *> _stableItems;
+ QSet<QFxItem *> _newItems;
+ QSet<QFxItem *> _animated;
+ QFxItem *_layoutItem;
+ QmlStateGroup *stateGroup;
+ QFxItem *_movingItem;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp
new file mode 100644
index 0000000..46166e2
--- /dev/null
+++ b/src/declarative/fx/qfxlistview.cpp
@@ -0,0 +1,1629 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qfxflickable_p.h"
+#include "qmlfollow.h"
+#include "qlistmodelinterface.h"
+#include "qfxvisualitemmodel.h"
+#include "qfxlistview.h"
+#include <qmlexpression.h>
+
+
+QT_BEGIN_NAMESPACE
+class QFxListViewAttached : public QObject
+{
+ Q_OBJECT
+public:
+ QFxListViewAttached(QObject *parent)
+ : QObject(parent), m_isCurrent(false), m_delayRemove(false) {}
+ ~QFxListViewAttached() {
+ attachedProperties.remove(parent());
+ }
+
+ Q_PROPERTY(QFxListView *view READ view);
+ QFxListView *view() { return m_view; }
+
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged);
+ bool isCurrentItem() const { return m_isCurrent; }
+ void setIsCurrentItem(bool c) {
+ if (m_isCurrent != c) {
+ m_isCurrent = c;
+ emit currentItemChanged();
+ }
+ }
+
+ Q_PROPERTY(QString prevSection READ prevSection NOTIFY prevSectionChanged);
+ QString prevSection() const { return m_prevSection; }
+ void setPrevSection(const QString &sect) {
+ if (m_prevSection != sect) {
+ m_prevSection = sect;
+ emit prevSectionChanged();
+ }
+ }
+
+ Q_PROPERTY(QString section READ section NOTIFY sectionChanged);
+ QString section() const { return m_section; }
+ void setSection(const QString &sect) {
+ if (m_section != sect) {
+ m_section = sect;
+ emit sectionChanged();
+ }
+ }
+
+ Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged);
+ bool delayRemove() const { return m_delayRemove; }
+ void setDelayRemove(bool delay) {
+ if (m_delayRemove != delay) {
+ m_delayRemove = delay;
+ emit delayRemoveChanged();
+ }
+ }
+
+ static QFxListViewAttached *properties(QObject *obj) {
+ QFxListViewAttached *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QFxListViewAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+ }
+
+ void emitAdd() { emit add(); }
+ void emitRemove() { emit remove(); }
+
+signals:
+ void currentItemChanged();
+ void sectionChanged();
+ void prevSectionChanged();
+ void delayRemoveChanged();
+ void add();
+ void remove();
+
+public:
+ QFxListView *m_view;
+ bool m_isCurrent;
+ mutable QString m_section;
+ QString m_prevSection;
+ bool m_delayRemove;
+
+ static QHash<QObject*, QFxListViewAttached*> attachedProperties;
+};
+
+QHash<QObject*, QFxListViewAttached*> QFxListViewAttached::attachedProperties;
+
+//----------------------------------------------------------------------------
+
+class FxListItem
+{
+public:
+ FxListItem(QFxItem *i, QFxListView *v) : item(i), view(v) {
+ attached = QFxListViewAttached::properties(item);
+ attached->m_view = view;
+ }
+ ~FxListItem() {}
+
+ qreal position() const { return (view->orientation() == Qt::Vertical ? item->y() : item->x()); }
+ int size() const { return (view->orientation() == Qt::Vertical ? item->height() : item->width()); }
+ qreal endPosition() const {
+ return (view->orientation() == Qt::Vertical
+ ? item->y() + (item->height() > 0 ? item->height() : 1)
+ : item->x() + (item->width() > 0 ? item->width() : 1)) - 1;
+ }
+ void setPosition(qreal pos) {
+ if (view->orientation() == Qt::Vertical) {
+ item->setY(pos);
+ } else {
+ item->setX(pos);
+ }
+ }
+
+ QFxItem *item;
+ QFxListView *view;
+ QFxListViewAttached *attached;
+ int index;
+};
+
+//----------------------------------------------------------------------------
+
+class QFxListViewPrivate : public QFxFlickablePrivate
+{
+ Q_DECLARE_PUBLIC(QFxListView);
+
+public:
+ QFxListViewPrivate()
+ : model(0), currentItem(0), tmpCurrent(0), orient(Qt::Vertical)
+ , visiblePos(0), visibleIndex(0)
+ , averageSize(100), currentIndex(-1), currItemMode(QFxListView::Free)
+ , snapPos(0), highlightComponent(0), highlight(0), trackedItem(0)
+ , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0)
+ , keyPressed(false), ownModel(false), wrap(false), autoHighlight(true)
+ , fixCurrentVisibility(false) {}
+
+ void init();
+ void clear();
+ FxListItem *getItem(int modelIndex);
+ FxListItem *createItem(int modelIndex);
+ void releaseItem(FxListItem *item);
+
+ FxListItem *visibleItem(int modelIndex) const {
+ if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
+ for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
+ FxListItem *item = visibleItems.at(i);
+ if (item->index == modelIndex)
+ return item;
+ }
+ }
+ return 0;
+ }
+
+ qreal position() const {
+ Q_Q(const QFxListView);
+ return orient == Qt::Vertical ? q->yPosition() : q->xPosition();
+ }
+ void setPosition(qreal pos) {
+ Q_Q(QFxListView);
+ if (orient == Qt::Vertical)
+ q->setYPosition(pos);
+ else
+ q->setXPosition(pos);
+ }
+ int size() const {
+ Q_Q(const QFxListView);
+ return orient == Qt::Vertical ? q->height() : q->width();
+ }
+
+ qreal startPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty())
+ pos = visibleItems.first()->position() - visibleIndex * averageSize;
+ return pos;
+ }
+
+ qreal endPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty()) {
+ int invisibleCount = visibleItems.count() - visibleIndex;
+ for (int i = visibleItems.count()-1; i >= 0; --i) {
+ if (visibleItems.at(i)->index != -1) {
+ invisibleCount = model->count() - visibleItems.at(i)->index - 1;
+ break;
+ }
+ }
+ pos = visibleItems.last()->endPosition() + invisibleCount * averageSize;
+ }
+ return pos;
+ }
+
+ qreal positionAt(int modelIndex) const {
+ if (FxListItem *item = visibleItem(modelIndex))
+ return item->position();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = visibleIndex - modelIndex;
+ return visibleItems.first()->position() - count * averageSize;
+ } else {
+ int idx = visibleItems.count() - 1;
+ while (idx >= 0 && visibleItems.at(idx)->index == -1)
+ --idx;
+ if (idx < 0)
+ idx = visibleIndex;
+ else
+ idx = visibleItems.at(idx)->index;
+ int count = modelIndex - idx - 1;
+ return visibleItems.last()->endPosition() + count * averageSize + 1;
+ }
+ }
+ return 0;
+ }
+
+ QString sectionAt(int modelIndex) {
+ Q_Q(QFxListView);
+ if (FxListItem *item = visibleItem(modelIndex))
+ return item->attached->section();
+ QString section;
+ if (!sectionExpression.isEmpty())
+ section = model->evaluate(modelIndex, sectionExpression, q).toString();
+ return section;
+ }
+
+ bool isValid() const {
+ return model && model->count() && (!ownModel || model->delegate());
+ }
+
+ int snapIndex() {
+ qreal pos = position();
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ qreal itemTop = visibleItems[i]->position() - pos;
+ if (itemTop >= snapPos-averageSize/2 && itemTop < snapPos+averageSize/2)
+ return visibleItems[i]->index;
+ }
+ return -1;
+ }
+
+ // map a model index to visibleItems 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) {
+ FxListItem *listItem = visibleItems.at(i);
+ if (listItem->index == modelIndex)
+ return i + visibleIndex;
+ if (listItem->index > modelIndex)
+ return -1;
+ }
+ return -1; // Not in visibleList
+ }
+
+ bool mapRangeFromModel(int &index, int &count) const {
+ if (index + count < visibleIndex)
+ return false;
+
+ int lastIndex = -1;
+ for (int i = visibleItems.count()-1; i >= 0; --i) {
+ FxListItem *listItem = visibleItems.at(i);
+ if (listItem->index != -1) {
+ lastIndex = listItem->index;
+ break;
+ }
+ }
+
+ if (index > lastIndex)
+ return false;
+
+ int last = qMin(index + count - 1, lastIndex);
+ index = qMax(index, visibleIndex);
+ count = last - index + 1;
+
+ return true;
+ }
+
+ // for debugging only
+ void checkVisible() const {
+ int skip = 0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem *listItem = visibleItems.at(i);
+ if (listItem->index == -1) {
+ ++skip;
+ } else if (listItem->index != visibleIndex + i - skip) {
+ qDebug() << "index" << visibleIndex << i << listItem->index;
+ abort();
+ }
+ }
+ }
+
+ void refill(qreal from, qreal to);
+ void layout();
+ void updateTrackedItem();
+ void createHighlight();
+ void updateHighlight();
+ void updateSections();
+ void updateCurrentSection();
+ void updateCurrent(int);
+ void updateAverage();
+ void fixupPosition();
+ virtual void fixupY();
+ virtual void fixupX();
+
+ QFxVisualItemModel *model;
+ QVariant modelVariant;
+ QList<FxListItem*> visibleItems;
+ FxListItem *currentItem;
+ QFxItem *tmpCurrent;
+ Qt::Orientation orient;
+ int visiblePos;
+ int visibleIndex;
+ qreal averageSize;
+ int currentIndex;
+ QFxListView::CurrentItemPositioning currItemMode;
+ int snapPos;
+ QmlComponent *highlightComponent;
+ FxListItem *highlight;
+ FxListItem *trackedItem;
+ QFxItem *activeItem; //XXX fix
+ enum MovementReason { Other, Key, Mouse };
+ MovementReason moveReason;
+ int buffer;
+ QmlFollow *highlightPosAnimator;
+ QmlFollow *highlightSizeAnimator;
+ QString sectionExpression;
+ QString currentSection;
+
+ int keyPressed : 1;
+ int ownModel : 1;
+ int wrap : 1;
+ int autoHighlight : 1;
+ int fixCurrentVisibility : 1;
+};
+
+void QFxListViewPrivate::init()
+{
+ Q_Q(QFxListView);
+ q->setOptions(QFxListView::IsFocusRealm);
+ QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(refill()));
+ QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(refill()));
+}
+
+void QFxListViewPrivate::clear()
+{
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ visiblePos = 0;
+ visibleIndex = 0;
+ if (currentItem) {
+ FxListItem *tmpItem = currentItem;
+ currentItem = 0;
+ currentIndex = -1;
+ releaseItem(tmpItem);
+ }
+ createHighlight();
+ trackedItem = 0;
+}
+
+FxListItem *QFxListViewPrivate::getItem(int modelIndex)
+{
+ if (currentItem && modelIndex == currentIndex)
+ return currentItem;
+ if (FxListItem *listItem = visibleItem(modelIndex))
+ return listItem;
+ return createItem(modelIndex);
+}
+
+FxListItem *QFxListViewPrivate::createItem(int modelIndex)
+{
+ Q_Q(QFxListView);
+ // create object
+ FxListItem *listItem = 0;
+ if (QFxItem *item = model->item(modelIndex, false)) {
+ listItem = new FxListItem(item, q);
+ listItem->index = modelIndex;
+ // initialise attached properties
+ if (!sectionExpression.isEmpty()) {
+ QmlExpression e(qmlContext(listItem->item), sectionExpression, q);
+ e.setTrackChange(false);
+ listItem->attached->m_section = e.value().toString();
+ if (modelIndex > 0) {
+ if (FxListItem *item = visibleItem(modelIndex-1))
+ listItem->attached->m_prevSection = item->attached->section();
+ else
+ listItem->attached->m_prevSection = sectionAt(modelIndex-1);
+ }
+ }
+ // complete
+ model->completeItem();
+ listItem->item->setZ(modelIndex + 1);
+ listItem->item->setParent(q->viewport());
+ if (orient == Qt::Vertical)
+ QObject::connect(listItem->item, SIGNAL(heightChanged()), q, SLOT(itemResized()));
+ else
+ QObject::connect(listItem->item, SIGNAL(widthChanged()), q, SLOT(itemResized()));
+ }
+
+ return listItem;
+}
+
+void QFxListViewPrivate::releaseItem(FxListItem *item)
+{
+ Q_Q(QFxListView);
+ if (item != currentItem) {
+ if (orient == Qt::Vertical)
+ QObject::disconnect(item->item, SIGNAL(heightChanged()), q, SLOT(itemResized()));
+ else
+ QObject::disconnect(item->item, SIGNAL(widthChanged()), q, SLOT(itemResized()));
+ if (trackedItem == item) {
+ const char *notifier1 = orient == Qt::Vertical ? SIGNAL(topChanged()) : SIGNAL(leftChanged());
+ const char *notifier2 = orient == Qt::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
+ QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+ model->release(item->item);
+ delete item;
+ }
+}
+
+void QFxListViewPrivate::refill(qreal from, qreal to)
+{
+ Q_Q(QFxListView);
+ if (!isValid() || !q->isComponentComplete())
+ return;
+ from -= buffer;
+ to += buffer;
+ int modelIndex = 0;
+ qreal itemEnd = visiblePos-1;
+ if (!visibleItems.isEmpty()) {
+ visiblePos = visibleItems.first()->position();
+ itemEnd = visibleItems.last()->endPosition();
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
+ --i;
+ modelIndex = visibleItems.at(i)->index + 1;
+ }
+
+ bool changed = false;
+ FxListItem *item = 0;
+ int pos = itemEnd + 1;
+ while (modelIndex < model->count() && pos <= to) {
+ //qDebug() << "refill: append item" << modelIndex;
+ if (!(item = getItem(modelIndex)))
+ break;
+ item->setPosition(pos);
+ pos += item->size();
+ visibleItems.append(item);
+ ++modelIndex;
+ changed = true;
+ }
+ while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > from) {
+ //qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos;
+ if (!(item = getItem(visibleIndex-1)))
+ break;
+ --visibleIndex;
+ visiblePos -= item->size();
+ item->setPosition(visiblePos);
+ visibleItems.prepend(item);
+ changed = true;
+ }
+
+ while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endPosition() < from) {
+ if (item->attached->delayRemove())
+ break;
+ //qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
+ if (item->index != -1)
+ visibleIndex++;
+ visibleItems.removeFirst();
+ releaseItem(item);
+ changed = true;
+ }
+ while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > to) {
+ if (item->attached->delayRemove())
+ break;
+ //qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+ visibleItems.removeLast();
+ releaseItem(item);
+ changed = true;
+ }
+ if (changed) {
+ if (visibleItems.count())
+ visiblePos = visibleItems.first()->position();
+ updateAverage();
+ if (!sectionExpression.isEmpty())
+ updateCurrentSection();
+ if (orient == Qt::Vertical)
+ q->setViewportHeight(endPosition() - startPosition());
+ else
+ q->setViewportWidth(endPosition() - startPosition());
+ }
+}
+
+void QFxListViewPrivate::layout()
+{
+ Q_Q(QFxListView);
+ if (!visibleItems.isEmpty()) {
+ int oldEnd = visibleItems.last()->endPosition();
+ int pos = visibleItems.first()->endPosition() + 1;
+ for (int i=1; i < visibleItems.count(); ++i) {
+ FxListItem *item = visibleItems.at(i);
+ item->setPosition(pos);
+ pos += item->size();
+ }
+ // move current item if it is after the visible items.
+ if (currentItem && currentIndex > visibleItems.last()->index)
+ currentItem->setPosition(currentItem->position() + (visibleItems.last()->endPosition() - oldEnd));
+ }
+ if (!isValid())
+ return;
+ q->refill();
+ q->trackedPositionChanged();
+ updateHighlight();
+ if (orient == Qt::Vertical) {
+ fixupY();
+ q->setViewportHeight(endPosition() - startPosition());
+ } else {
+ fixupX();
+ q->setViewportWidth(endPosition() - startPosition());
+ }
+}
+
+void QFxListViewPrivate::updateTrackedItem()
+{
+ Q_Q(QFxListView);
+ FxListItem *item = currentItem;
+ if (highlight)
+ item = highlight;
+
+ const char *notifier1 = orient == Qt::Vertical ? SIGNAL(topChanged()) : SIGNAL(leftChanged());
+ const char *notifier2 = orient == Qt::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
+
+ if (trackedItem && item != trackedItem) {
+ QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+
+ if (!trackedItem && item) {
+ trackedItem = item;
+ QObject::connect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
+ QObject::connect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
+ q->trackedPositionChanged();
+ }
+ if (trackedItem)
+ q->trackedPositionChanged();
+}
+
+void QFxListViewPrivate::createHighlight()
+{
+ Q_Q(QFxListView);
+ if (highlight) {
+ if (trackedItem == highlight)
+ trackedItem = 0;
+ delete highlight->item;
+ delete highlight;
+ highlight = 0;
+ delete highlightPosAnimator;
+ delete highlightSizeAnimator;
+ highlightPosAnimator = 0;
+ highlightSizeAnimator = 0;
+ }
+
+ if (currentItem) {
+ QFxItem *item = 0;
+ if (highlightComponent) {
+ QmlContext *highlightContext = new QmlContext(qmlContext(q));
+ QObject *nobj = highlightComponent->create(highlightContext);
+ if (nobj) {
+ highlightContext->setParent(nobj);
+ item = qobject_cast<QFxItem *>(nobj);
+ if (!item) {
+ delete nobj;
+ } else {
+ item->setParent(q->viewport());
+ }
+ } else {
+ delete highlightContext;
+ }
+ } else {
+ item = new QFxItem;
+ item->setParent(q->viewport());
+ }
+ if (item) {
+ highlight = new FxListItem(item, q);
+ const QLatin1String posProp(orient == Qt::Vertical ? "y" : "x");
+ highlightPosAnimator = new QmlFollow(q);
+ highlightPosAnimator->setTarget(QmlMetaProperty(highlight->item, posProp));
+ highlightPosAnimator->setSpring(3);
+ highlightPosAnimator->setDamping(0.3);
+ highlightPosAnimator->setEnabled(autoHighlight);
+ const QLatin1String sizeProp(orient == Qt::Vertical ? "height" : "width");
+ highlightSizeAnimator = new QmlFollow(q);
+ highlightSizeAnimator->setTarget(QmlMetaProperty(highlight->item, sizeProp));
+ highlightSizeAnimator->setEnabled(autoHighlight);
+ }
+ }
+}
+
+void QFxListViewPrivate::updateHighlight()
+{
+ if ((!currentItem && highlight) || (currentItem && !highlight))
+ createHighlight();
+ updateTrackedItem();
+ if (currentItem && autoHighlight && highlight) {
+ // auto-update highlight
+ highlightPosAnimator->setSourceValue(currentItem->position());
+ highlightSizeAnimator->setSourceValue(currentItem->size());
+ if (orient == Qt::Vertical) {
+ if (highlight->item->width() == 0)
+ highlight->item->setWidth(currentItem->item->width());
+ } else {
+ if (highlight->item->height() == 0)
+ highlight->item->setHeight(currentItem->item->height());
+ }
+ }
+}
+
+void QFxListViewPrivate::updateSections()
+{
+ if (!sectionExpression.isEmpty()) {
+ QString prevSection;
+ if (visibleIndex > 0)
+ prevSection = sectionAt(visibleIndex-1);
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ QFxListViewAttached *attached = visibleItems.at(i)->attached;
+ attached->setPrevSection(prevSection);
+ prevSection = attached->section();
+ }
+ }
+}
+
+void QFxListViewPrivate::updateCurrentSection()
+{
+ if (sectionExpression.isEmpty() || visibleItems.isEmpty()) {
+ currentSection = QString();
+ return;
+ }
+ int index = 0;
+ while (visibleItems.at(index)->endPosition() < position() && index < visibleItems.count())
+ ++index;
+
+ if (index < visibleItems.count())
+ currentSection = visibleItems.at(index)->attached->section();
+ else
+ currentSection = visibleItems.first()->attached->section();
+}
+
+void QFxListViewPrivate::updateCurrent(int modelIndex)
+{
+ Q_Q(QFxListView);
+ if (!isValid() || modelIndex < 0 || modelIndex >= model->count()) {
+ if (currentItem) {
+ FxListItem *item = currentItem;
+ int index = currentIndex;
+ currentItem = 0;
+ currentIndex = 0;
+ updateHighlight();
+ if (!visibleItem(index))
+ releaseItem(item);
+ emit q->currentIndexChanged();
+ }
+ return;
+ }
+
+ if (currentItem && currentIndex == modelIndex) {
+ updateHighlight();
+ return;
+ }
+
+ if (tmpCurrent) {
+ delete tmpCurrent;
+ tmpCurrent = 0;
+ }
+ int oldCurrentIndex = currentIndex;
+ FxListItem *oldCurrentItem = currentItem;
+ currentIndex = -1;
+ currentItem = visibleItem(modelIndex);
+ if (!currentItem) {
+ currentItem = getItem(modelIndex);
+ if (currentItem) {
+ if (modelIndex == visibleIndex - 1) {
+ // We can calculate exact postion in this case
+ currentItem->setPosition(visibleItems.first()->position() - currentItem->size());
+ } else {
+ // Create current item now and position as best we can.
+ // Its position will be corrected when it becomes visible.
+ currentItem->setPosition(positionAt(modelIndex));
+ }
+ }
+ }
+ currentIndex = modelIndex;
+ fixCurrentVisibility = true;
+ if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
+ oldCurrentItem->attached->setIsCurrentItem(false);
+ if (currentItem) {
+ currentItem->item->setFocus(true);
+ currentItem->attached->setIsCurrentItem(true);
+ }
+ updateHighlight();
+ emit q->currentIndexChanged();
+ // Release the old current item
+ if (oldCurrentItem && !visibleItem(oldCurrentIndex)) {
+ if (!currentItem || oldCurrentItem->item == currentItem->item)
+ delete oldCurrentItem;
+ else
+ releaseItem(oldCurrentItem);
+ }
+}
+
+void QFxListViewPrivate::updateAverage()
+{
+ if (!visibleItems.count())
+ return;
+ qreal sum = 0.0;
+ for (int i = 0; i < visibleItems.count(); ++i)
+ sum += visibleItems.at(i)->size();
+ averageSize = sum / visibleItems.count();
+}
+
+void QFxListViewPrivate::fixupPosition()
+{
+ if (orient == Qt::Vertical)
+ fixupY();
+ else
+ fixupX();
+}
+
+void QFxListViewPrivate::fixupY()
+{
+ Q_Q(QFxListView);
+ QFxFlickablePrivate::fixupY();
+ if (orient == Qt::Horizontal)
+ return;
+ if (currItemMode == QFxListView::SnapAuto) {
+ if (currentItem) {
+ moveReason = Mouse;
+ _tl.clear();
+ _tl.move(_moveY, -(currentItem->position() - snapPos), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ }
+ } else if (currItemMode == QFxListView::Snap) {
+ moveReason = Mouse;
+ int idx = snapIndex();
+ if (FxListItem *snapItem = visibleItem(idx)) {
+ int pos = snapItem->position() - snapPos;
+ if (pos > -q->maxYExtent())
+ pos = -q->maxYExtent();
+ else if (pos < -q->minYExtent())
+ pos = -q->minYExtent();
+ _tl.clear();
+ _tl.move(_moveY, -(pos), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ }
+ }
+}
+
+void QFxListViewPrivate::fixupX()
+{
+ Q_Q(QFxListView);
+ QFxFlickablePrivate::fixupX();
+ if (orient == Qt::Vertical)
+ return;
+ if (currItemMode == QFxListView::SnapAuto) {
+ moveReason = Mouse;
+ _tl.clear();
+ _tl.move(_moveX, -(currentItem->position() - snapPos), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ } else if (currItemMode == QFxListView::Snap) {
+ moveReason = Mouse;
+ int idx = snapIndex();
+ if (FxListItem *snapItem = visibleItem(idx)) {
+ int pos = snapItem->position() - snapPos;
+ if (pos > -q->maxXExtent())
+ pos = -q->maxXExtent();
+ else if (pos < -q->minXExtent())
+ pos = -q->minXExtent();
+ _tl.clear();
+ _tl.move(_moveX, -(pos), QEasingCurve(QEasingCurve::InOutQuad), 200);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
+/*!
+ \qmlclass ListView
+ \inherits Flickable
+ \brief The ListView item provides a list view of items provided by a model.
+
+ The model is typically provided by a QAbstractListModel "C++ model object", but can also be created directly in QML.
+ The items are laid out vertically or horizontally and may be flicked to scroll.
+
+ The below example creates a very simple vertical list, using a QML model.
+ \image trivialListView.png
+
+ The user interface defines a delegate to display an item, a highlight,
+ and the ListView which uses the above.
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml 3
+
+ The model is defined as a ListModel using QML:
+ \quotefile doc/src/snippets/declarative/listview/dummydata/ContactModel.qml
+
+ In this case ListModel is a handy way for us to test our UI. In practice
+ the model would be implemented in C++, or perhaps via a SQL data source.
+*/
+
+QFxListView::QFxListView(QFxItem *parent)
+ : QFxFlickable(*(new QFxListViewPrivate), parent)
+{
+ Q_D(QFxListView);
+ d->init();
+}
+
+QFxListView::~QFxListView()
+{
+ Q_D(QFxListView);
+ if (d->ownModel)
+ delete d->model;
+}
+
+/*!
+ \qmlproperty model ListView::model
+ This property holds the model providing data for the list.
+
+ The model provides a set of data that is used to create the items
+ for the view. For large or dynamic datasets the model is usually
+ provided by a C++ model object. The C++ model object must be a \l
+ {QAbstractItemModel} subclass, a VisualModel, or a simple list.
+
+ Models can also be created directly in QML, using a \l{ListModel}.
+*/
+QVariant QFxListView::model() const
+{
+ Q_D(const QFxListView);
+ return d->modelVariant;
+}
+
+void QFxListView::setModel(const QVariant &model)
+{
+ Q_D(QFxListView);
+ 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)));
+ }
+ d->clear();
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QFxVisualItemModel *vim = 0;
+ if (object && (vim = qobject_cast<QFxVisualItemModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QFxVisualItemModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ d->model->setModel(model);
+ }
+ if (d->model) {
+ if (d->currentIndex >= d->model->count() || d->currentIndex < 0)
+ setCurrentIndex(0);
+ else
+ d->updateCurrent(d->currentIndex);
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ refill();
+ emit countChanged();
+ }
+}
+
+/*!
+ \qmlproperty component ListView::delegate
+
+ The delegate provides a template describing what each item in the view should look and act like.
+
+ Here is an example delegate:
+ \snippet doc/src/snippets/declarative/listview/listview.qml 0
+*/
+QmlComponent *QFxListView::delegate() const
+{
+ Q_D(const QFxListView);
+ return d->model ? d->model->delegate() : 0;
+}
+
+void QFxListView::setDelegate(QmlComponent *delegate)
+{
+ Q_D(QFxListView);
+ if (!d->ownModel) {
+ d->model = new QFxVisualItemModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ d->model->setDelegate(delegate);
+ d->updateCurrent(d->currentIndex);
+ refill();
+}
+
+/*!
+ \qmlproperty int ListView::currentIndex
+ \qmlproperty Item ListView::current
+
+ \c currentIndex holds the index of the current item.
+ \c current is the current item. Note that the position of the current item
+ may only be approximate until it becomes visible in the view.
+*/
+int QFxListView::currentIndex() const
+{
+ Q_D(const QFxListView);
+ return d->currentIndex;
+}
+
+void QFxListView::setCurrentIndex(int index)
+{
+ Q_D(QFxListView);
+ d->moveReason = QFxListViewPrivate::Other;
+ if (d->isValid() && index != d->currentIndex && index < d->model->count() && index >= 0)
+ d->updateCurrent(index);
+ else
+ d->currentIndex = index;
+}
+
+QFxItem *QFxListView::currentItem()
+{
+ Q_D(QFxListView);
+ if (!d->currentItem) {
+ // Always return something valid
+ if (!d->tmpCurrent) {
+ d->tmpCurrent = new QFxItem;
+ d->tmpCurrent->setParent(viewport());
+ }
+ return d->tmpCurrent;
+ }
+ return d->currentItem->item;
+}
+
+/*!
+ \qmlproperty int ListView::count
+ This property holds the number of items in the view.
+*/
+int QFxListView::count() const
+{
+ Q_D(const QFxListView);
+ if (d->model)
+ return d->model->count();
+ return 0;
+}
+
+/*!
+ \qmlproperty component ListView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component will be created for each list.
+ The geometry of the resultant component instance will be managed by the list
+ so as to stay with the current item, unless the autoHighlight property is false.
+
+ The below example demonstrates how to make a simple highlight
+ for a vertical list.
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml 1
+ \image trivialListView.png
+
+ \sa autoHighlight
+*/
+QmlComponent *QFxListView::highlight() const
+{
+ Q_D(const QFxListView);
+ return d->highlightComponent;
+}
+
+void QFxListView::setHighlight(QmlComponent *highlight)
+{
+ Q_D(QFxListView);
+ delete d->highlightComponent;
+ d->highlightComponent = highlight;
+ d->updateCurrent(d->currentIndex);
+}
+
+/*!
+ \qmlproperty bool ListView::autoHighlight
+ This property holds whether the highlight is managed by the view.
+
+ If autoHighlight is true, the highlight will be moved smoothly
+ to follow the current item. If autoHighlight is false, the
+ highlight will not be moved by the view, and must be implemented
+ by the highlight. The following example creates a highlight with
+ its motion defined by the spring \l {Follow}:
+
+ \snippet doc/src/snippets/declarative/listview/highlight.qml 1
+
+ \sa highlight
+*/
+bool QFxListView::autoHighlight() const
+{
+ Q_D(const QFxListView);
+ return d->autoHighlight;
+}
+
+void QFxListView::setAutoHighlight(bool autoHighlight)
+{
+ Q_D(QFxListView);
+ d->autoHighlight = autoHighlight;
+ if (d->highlightPosAnimator) {
+ d->highlightPosAnimator->setEnabled(d->autoHighlight);
+ d->highlightSizeAnimator->setEnabled(d->autoHighlight);
+ }
+ d->updateHighlight();
+}
+
+/*!
+ \qmlproperty enumeration ListView::currentItemPositioning
+ This property determines the current item positioning and selection characteristics.
+
+ The modes supported are:
+ \list
+ \i Free - For Mouse, the current item may be positioned anywhere,
+ whether within the visible area, or outside. During Keyboard interaction,
+ the current item can move within the visible area, and the view will
+ scroll to keep the highlight visible.
+ \i Snap - For mouse, the current item may be positioned anywhere,
+ whether within the visible area, or outside. During keyboard interaction,
+ the current item will be kept in the visible area and will prefer to be
+ positioned at the \l snapPosition, however the view will never scroll
+ beyond the beginning or end of the view.
+ \i SnapAuto - For both mouse and keyboard, the current item will be
+ kept at the \l {snapPosition}. Additionally, if the view is dragged or
+ flicked, the current item will be automatically updated to be the item
+ currently at the snapPosition.
+ \endlist
+*/
+QFxListView::CurrentItemPositioning QFxListView::currentItemPositioning() const
+{
+ Q_D(const QFxListView);
+ return d->currItemMode;
+}
+
+void QFxListView::setCurrentItemPositioning(CurrentItemPositioning mode)
+{
+ Q_D(QFxListView);
+ d->currItemMode = mode;
+}
+
+/*!
+ \qmlproperty int ListView::snapPosition
+
+ When currentItemPositioning is set to Snap or SnapAuto, the
+ \c snapPosition determines where the top of the items will
+ snap to.
+*/
+int QFxListView::snapPosition() const
+{
+ Q_D(const QFxListView);
+ return d->snapPos;
+}
+
+void QFxListView::setSnapPosition(int pos)
+{
+ Q_D(QFxListView);
+ d->snapPos = pos;
+}
+
+/*!
+ \qmlproperty enumeration ListView::orientation
+ This property holds the orientation of the list.
+
+ Possible values are \c Vertical (default) and \c Horizontal.
+
+ Vertical Example:
+ \image trivialListView.png
+ Horizontal Example:
+ \image ListViewHorizontal.png
+*/
+Qt::Orientation QFxListView::orientation() const
+{
+ Q_D(const QFxListView);
+ return d->orient;
+}
+
+void QFxListView::setOrientation(Qt::Orientation orientation)
+{
+ Q_D(QFxListView);
+ if (d->orient != orientation) {
+ d->orient = orientation;
+ if (d->orient == Qt::Vertical)
+ setViewportWidth(-1);
+ else
+ setViewportHeight(-1);
+ d->clear();
+ refill();
+ d->updateCurrent(d->currentIndex);
+ }
+}
+
+/*!
+ \qmlproperty bool ListView::wrap
+ This property holds whether the list wraps key navigation
+
+ If this property is true then key presses to move off of one end of the list will cause the
+ selection to jump to the other side.
+*/
+bool QFxListView::isWrapEnabled() const
+{
+ Q_D(const QFxListView);
+ return d->wrap;
+}
+
+void QFxListView::setWrapEnabled(bool wrap)
+{
+ Q_D(QFxListView);
+ d->wrap = wrap;
+}
+
+/*!
+ \qmlproperty int ListView::cacheBuffer
+ This property holds the number of off-screen pixels to cache.
+
+ This property determines the number of pixels above the top of the list
+ and below the bottom of the list to cache. Setting this value can make
+ scrolling the list smoother at the expense of additional memory usage.
+*/
+
+/*!
+ \property QFxListView::cacheBuffer
+ \brief sets the number of off-screen pixels to cache.
+
+ This property determines the number of pixels above the top of the list
+ and below the bottom of the list to cache. Setting this value can make
+ scrolling the list smoother at the expense of additional memory usage.
+*/
+int QFxListView::cacheBuffer() const
+{
+ Q_D(const QFxListView);
+ return d->buffer;
+}
+
+void QFxListView::setCacheBuffer(int b)
+{
+ Q_D(QFxListView);
+ if (d->buffer != b) {
+ d->buffer = b;
+ if (isComponentComplete())
+ refill();
+ }
+}
+
+/*!
+ \qmlproperty string ListView::sectionExpression
+ This property holds the expression to be evaluated for the section attached property.
+
+ Each item in the list has attached properties named \c ListView.section and
+ \c ListView.prevSection. These may be used to place a section header for
+ related items. The example below assumes that the model is sorted by size of
+ pet. The section expression is the size property. If \c ListView.section and
+ \c ListView.prevSection differ, the item will display a section header.
+
+ \snippet examples/declarative/listview/sections.qml 0
+
+ \image ListViewSections.png
+*/
+QString QFxListView::sectionExpression() const
+{
+ Q_D(const QFxListView);
+ return d->sectionExpression;
+}
+
+void QFxListView::setSectionExpression(const QString &expression)
+{
+ Q_D(QFxListView);
+ if (d->sectionExpression != expression) {
+ d->sectionExpression = expression;
+ emit sectionExpressionChanged();
+ }
+}
+
+QString QFxListView::currentSection() const
+{
+ Q_D(const QFxListView);
+ return d->currentSection;
+}
+
+void QFxListView::viewportMoved()
+{
+ Q_D(QFxListView);
+ QFxFlickable::viewportMoved();
+ refill();
+ if (isFlicking() || d->pressed)
+ d->moveReason = QFxListViewPrivate::Mouse;
+ if (d->currItemMode == SnapAuto && d->moveReason == QFxListViewPrivate::Mouse) {
+ // Update current index
+ int idx = d->snapIndex();
+ if (idx >= 0 && idx != d->currentIndex)
+ d->updateCurrent(idx);
+ }
+}
+
+/*!
+ \reimp
+*/
+qreal QFxListView::minYExtent() const
+{
+ Q_D(const QFxListView);
+ if (d->orient == Qt::Horizontal)
+ return QFxFlickable::minYExtent();
+ qreal extent = -d->startPosition();
+ if (d->currItemMode == SnapAuto)
+ extent += d->snapPos;
+
+ return extent;
+}
+
+/*!
+ \reimp
+*/
+qreal QFxListView::maxYExtent() const
+{
+ Q_D(const QFxListView);
+ if (d->orient == Qt::Horizontal)
+ return QFxFlickable::maxYExtent();
+ qreal extent;
+ if (d->currItemMode == SnapAuto)
+ extent = -(d->positionAt(count()-1) - d->snapPos);
+ else
+ extent = -(d->endPosition() - height());
+ if (extent > 0)
+ extent = 0;
+ return extent;
+}
+
+/*!
+ \reimp
+*/
+qreal QFxListView::minXExtent() const
+{
+ Q_D(const QFxListView);
+ if (d->orient == Qt::Vertical)
+ return QFxFlickable::minXExtent();
+ qreal extent = -d->startPosition();
+ if (d->currItemMode == SnapAuto)
+ extent += d->snapPos;
+
+ return extent;
+}
+
+/*!
+ \reimp
+*/
+qreal QFxListView::maxXExtent() const
+{
+ Q_D(const QFxListView);
+ if (d->orient == Qt::Vertical)
+ return QFxFlickable::maxXExtent();
+ qreal extent;
+ if (d->currItemMode == SnapAuto)
+ extent = -(d->positionAt(count()-1) - d->snapPos);
+ else
+ extent = -(d->endPosition() - width());
+ if (extent > 0)
+ extent = 0;
+ return extent;
+}
+
+void QFxListView::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QFxListView);
+ if (d->model && d->model->count() && !d->locked) {
+ if ((d->orient == Qt::Horizontal && event->key() == Qt::Key_Left)
+ || (d->orient == Qt::Vertical && event->key() == Qt::Key_Up)) {
+ if (currentIndex() > 0 || d->wrap) {
+ d->keyPressed = true;
+ d->moveReason = QFxListViewPrivate::Key;
+ int index = currentIndex()-1;
+ d->updateCurrent(index >= 0 ? index : d->model->count()-1);
+ event->accept();
+ }
+ return;
+ } else if ((d->orient == Qt::Horizontal && event->key() == Qt::Key_Right)
+ || (d->orient == Qt::Vertical && event->key() == Qt::Key_Down)) {
+ if (currentIndex() < d->model->count() - 1 || d->wrap) {
+ d->keyPressed = true;
+ d->moveReason = QFxListViewPrivate::Key;
+ int index = currentIndex()+1;
+ d->updateCurrent(index < d->model->count() ? index : 0);
+ event->accept();
+ }
+ return;
+ }
+ }
+ d->moveReason = QFxListViewPrivate::Other;
+ QFxFlickable::keyPressEvent(event);
+}
+
+void QFxListView::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QFxListView);
+ d->keyPressed = false;
+ QFxFlickable::keyReleaseEvent(event);
+}
+
+void QFxListView::componentComplete()
+{
+ Q_D(QFxListView);
+ QFxFlickable::componentComplete();
+ if (d->currentIndex < 0)
+ d->updateCurrent(0);
+ refill();
+ d->fixupPosition();
+}
+
+void QFxListView::refill()
+{
+ Q_D(QFxListView);
+ d->refill(d->position(), d->position()+d->size()-1);
+}
+
+void QFxListView::trackedPositionChanged()
+{
+ Q_D(QFxListView);
+ if (!d->trackedItem)
+ return;
+ if (!isFlicking() && !d->pressed && d->moveReason != QFxListViewPrivate::Mouse) {
+ switch (d->currItemMode) {
+ case Free:
+ if (d->trackedItem->position() < d->position()) {
+ d->setPosition(d->trackedItem->position());
+ } else if (d->trackedItem->endPosition() > d->position() + d->size()) {
+ qreal pos = d->trackedItem->endPosition() - d->size();
+ if (d->trackedItem->size() > d->size())
+ pos = d->trackedItem->position();
+ d->setPosition(pos);
+ }
+ d->fixupPosition();
+ break;
+ case Snap:
+ if (d->trackedItem->position() < d->startPosition() + d->snapPos)
+ d->setPosition(d->startPosition());
+ else if (d->trackedItem->endPosition() > d->endPosition() - d->size() + d->snapPos + d->trackedItem->size())
+ d->setPosition(d->endPosition() - d->size());
+ else
+ d->setPosition(d->trackedItem->position() - d->snapPos);
+ break;
+ case SnapAuto:
+ d->setPosition(d->trackedItem->position() - d->snapPos);
+ break;
+ }
+ } else if (d->fixCurrentVisibility && d->currentItem && !d->pressed) {
+ /*
+ if (d->trackedItem->position() < d->position()
+ && d->currentItem->position() < d->position()) {
+ d->setPosition(d->trackedItem->position());
+ } else if (d->size() && d->trackedItem->size() <= d->size()
+ && d->trackedItem->endPosition() > d->position() + d->size()
+ && d->currentItem->endPosition() > d->position() + d->size()) {
+ d->setPosition(d->trackedItem->endPosition() - d->size());
+ }
+ if (d->trackedItem->position() == d->currentItem->position())
+ d->fixCurrentVisibility = false;
+ */
+ }
+}
+
+void QFxListView::itemResized()
+{
+ Q_D(QFxListView);
+ QFxItem *item = qobject_cast<QFxItem*>(sender());
+ if (item) {
+ d->activeItem = item; // Ick - don't delete the sender
+ d->layout();
+ d->activeItem = 0;
+ d->fixupPosition();
+ }
+}
+
+void QFxListView::itemsInserted(int modelIndex, int count)
+{
+ Q_D(QFxListView);
+ if (!d->visibleItems.count() || d->model->count() <= 1) {
+ d->layout();
+ d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1)));
+ emit countChanged();
+ return;
+ }
+
+ if (!d->mapRangeFromModel(modelIndex, count)) {
+ int i = d->visibleItems.count() - 1;
+ while (i > 0 && d->visibleItems.at(i)->index == -1)
+ --i;
+ if (d->visibleItems.at(i)->index + 1 == modelIndex) {
+ // Special case of appending an item to the model.
+ modelIndex = d->visibleIndex + d->visibleItems.count();
+ } else {
+ if (modelIndex + count - 1 < d->visibleIndex) {
+ // Insert before visible items
+ d->visibleIndex += count;
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxListItem *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1 && listItem != d->currentItem)
+ listItem->index += count;
+ }
+ }
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem)
+ d->currentItem->index = d->currentIndex;
+ }
+ d->layout();
+ emit countChanged();
+ return;
+ }
+ }
+
+ // At least some of the added items will be visible
+
+ int index = modelIndex - d->visibleIndex;
+ int to = d->buffer+d->position()+d->size()-1;
+ // index can be the next item past the end of the visible items list (i.e. appended)
+ int pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position()
+ : d->visibleItems.at(index-1)->endPosition()+1;
+ int initialPos = pos;
+ QList<FxListItem*> added;
+ for (int i = 0; i < count && pos <= to; ++i) {
+ FxListItem *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(index, item);
+ item->setPosition(pos);
+ added.append(item);
+ pos += item->size();
+ ++index;
+ }
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem) {
+ d->currentItem->index = d->currentIndex;
+ d->currentItem->setPosition(d->currentItem->position() + (pos - initialPos));
+ }
+ }
+ if (pos > to) {
+ // We didn't insert all our new items, which means anything
+ // beyond the current index is not visible - remove it.
+ while (d->visibleItems.count() > index)
+ d->releaseItem(d->visibleItems.takeLast());
+ } else {
+ // Update the indexes of the following visible items.
+ for (; index < d->visibleItems.count(); ++index) {
+ FxListItem *listItem = d->visibleItems.at(index);
+ if (listItem != d->currentItem) {
+ listItem->setPosition(listItem->position() + (pos - initialPos));
+ if (listItem->index != -1)
+ listItem->index += count;
+ }
+ }
+ }
+ // everything is in order now - emit add() signal
+ for (int j = 0; j < added.count(); ++j)
+ added.at(j)->attached->emitAdd();
+ emit countChanged();
+}
+
+void QFxListView::itemsRemoved(int modelIndex, int count)
+{
+ Q_D(QFxListView);
+ if (!d->mapRangeFromModel(modelIndex, count)) {
+ if (modelIndex + count - 1 < d->visibleIndex) {
+ // Items removed before our visible items.
+ d->visibleIndex -= count;
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxListItem *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1 && listItem != d->currentItem)
+ listItem->index -= count;
+ }
+ }
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ if (d->currentItem)
+ d->currentItem->index -= count;
+ } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
+ // current item has been removed.
+ if (d->currentItem) {
+ FxListItem *item = d->currentItem;
+ d->currentItem = 0;
+ d->releaseItem(item);
+ }
+ d->currentIndex = -1;
+ d->updateCurrent(qMin(modelIndex, d->model->count()-1));
+ }
+ d->layout();
+ emit countChanged();
+ return;
+ }
+
+ // Remove the items from the visible list, skipping anything already marked for removal
+ QList<FxListItem*>::Iterator it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxListItem *item = *it;
+ if (item->index == -1 || item->index < modelIndex) {
+ // already removed, or before removed items
+ ++it;
+ } else if (item->index >= modelIndex + count) {
+ // after removed items
+ if (item != d->currentItem)
+ item->index -= count;
+ ++it;
+ } else {
+ // removed item
+ item->attached->emitRemove();
+ if (item->attached->delayRemove()) {
+ item->index = -1;
+ connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
+ ++it;
+ } else {
+ it = d->visibleItems.erase(it);
+ d->releaseItem(item);
+ }
+ }
+ }
+
+ // fix current
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ if (d->currentItem)
+ d->currentItem->index -= count;
+ } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
+ // current item has been removed.
+ if (d->currentItem && !d->currentItem->attached->delayRemove()) {
+ FxListItem *item = d->currentItem;
+ d->currentItem = 0;
+ d->releaseItem(item);
+ }
+ d->currentItem = 0;
+ d->currentIndex = -1;
+ d->updateCurrent(qMin(modelIndex, d->model->count()-1));
+ }
+
+ // update visibleIndex
+ for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ d->visibleIndex = (*it)->index;
+ break;
+ }
+ }
+
+ if (d->visibleItems.isEmpty()) {
+ d->visibleIndex = 0;
+ d->visiblePos = 0;
+ d->_tl.clear();
+ d->setPosition(0);
+ if (d->model->count() == 0)
+ update();
+ else
+ refill();
+ } else {
+ // Correct the positioning of the items
+ d->layout();
+ }
+
+ emit countChanged();
+}
+
+void QFxListView::destroyRemoved()
+{
+ Q_D(QFxListView);
+ for (QList<FxListItem*>::Iterator it = d->visibleItems.begin();
+ it != d->visibleItems.end();) {
+ FxListItem *listItem = *it;
+ if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
+ d->releaseItem(listItem);
+ it = d->visibleItems.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ // Correct the positioning of the items
+ d->layout();
+}
+
+QObject *QFxListView::qmlAttachedProperties(QObject *obj)
+{
+ return QFxListViewAttached::properties(obj);
+}
+
+QML_DEFINE_TYPE(QFxListView,ListView);
+
+QT_END_NAMESPACE
+#include "qfxlistview.moc"
diff --git a/src/declarative/fx/qfxlistview.h b/src/declarative/fx/qfxlistview.h
new file mode 100644
index 0000000..40c2496
--- /dev/null
+++ b/src/declarative/fx/qfxlistview.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXLISTVIEW_H
+#define QFXLISTVIEW_H
+
+#include <qfxflickable.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxVisualItemModel;
+class QFxListViewPrivate;
+class Q_DECLARATIVE_EXPORT QFxListView : public QFxFlickable
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFxListView);
+
+ Q_ENUMS(CurrentItemPositioning);
+ Q_PROPERTY(QVariant model READ model WRITE setModel);
+ Q_CLASSINFO("DefaultProperty", "delegate");
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate);
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged);
+ Q_PROPERTY(QFxItem *current READ currentItem NOTIFY currentIndexChanged);
+ Q_PROPERTY(int count READ count NOTIFY countChanged);
+ Q_PROPERTY(QmlComponent *highlight READ highlight WRITE setHighlight);
+ Q_PROPERTY(bool autoHighlight READ autoHighlight WRITE setAutoHighlight);
+ Q_PROPERTY(CurrentItemPositioning currentItemPositioning READ currentItemPositioning WRITE setCurrentItemPositioning);
+ Q_PROPERTY(int snapPosition READ snapPosition WRITE setSnapPosition);
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation);
+ Q_PROPERTY(bool wrap READ isWrapEnabled WRITE setWrapEnabled);
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer);
+ Q_PROPERTY(QString sectionExpression READ sectionExpression WRITE setSectionExpression NOTIFY sectionExpressionChanged);
+ Q_PROPERTY(QString currentSection READ currentSection NOTIFY currentSectionChanged);
+
+public:
+ QFxListView(QFxItem *parent=0);
+ ~QFxListView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ QFxItem *currentItem();
+ int count() const;
+
+ QmlComponent *highlight() const;
+ void setHighlight(QmlComponent *highlight);
+
+ bool autoHighlight() const;
+ void setAutoHighlight(bool);
+
+ enum CurrentItemPositioning { Free, Snap, SnapAuto };
+ CurrentItemPositioning currentItemPositioning() const;
+ void setCurrentItemPositioning(CurrentItemPositioning mode);
+
+ int snapPosition() const;
+ void setSnapPosition(int pos);
+
+ Qt::Orientation orientation() const;
+ void setOrientation(Qt::Orientation);
+
+ bool isWrapEnabled() const;
+ void setWrapEnabled(bool);
+
+ int cacheBuffer() const;
+ void setCacheBuffer(int);
+
+ QString sectionExpression() const;
+ void setSectionExpression(const QString &);
+ QString currentSection() const;
+
+ static QObject *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void countChanged();
+ void currentIndexChanged();
+ void currentSectionChanged();
+ void sectionExpressionChanged();
+
+protected:
+ virtual void viewportMoved();
+ virtual qreal minYExtent() const;
+ virtual qreal maxYExtent() const;
+ virtual qreal minXExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void componentComplete();
+
+private Q_SLOTS:
+ void refill();
+ void trackedPositionChanged();
+ void itemResized();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void destroyRemoved();
+};
+
+QML_DECLARE_TYPE(QFxListView);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/fx/qfxmouseregion.cpp b/src/declarative/fx/qfxmouseregion.cpp
new file mode 100644
index 0000000..a60ddc4
--- /dev/null
+++ b/src/declarative/fx/qfxmouseregion.cpp
@@ -0,0 +1,580 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxmouseregion.h"
+#include "qfxmouseregion_p.h"
+#include "qfxevents_p.h"
+#include <QGraphicsSceneMouseEvent>
+
+
+QT_BEGIN_NAMESPACE
+static const int DragThreshold = 5;
+static const int PressAndHoldDelay = 800;
+
+QML_DEFINE_TYPE(QFxDrag,Drag);
+QFxDrag::QFxDrag(QObject *parent)
+: QObject(parent), _target(0), _xmin(0), _xmax(0), _ymin(0), _ymax(0)
+{
+}
+
+QFxDrag::~QFxDrag()
+{
+}
+
+QFxItem *QFxDrag::target() const
+{
+ return _target;
+}
+
+void QFxDrag::setTarget(QFxItem *t)
+{
+ _target = t;
+}
+
+QString QFxDrag::axis() const
+{
+ return _axis;
+}
+
+void QFxDrag::setAxis(const QString &a)
+{
+ _axis = a;
+}
+
+/*!
+ \property QFxDrag::xmin
+ \brief the minimum x position for the target
+
+ If x-axis dragging is enabled, xmin limits how far to the left the target can be dragged. If x-axis dragging is not enabled, this property has no effect.
+*/
+int QFxDrag::xmin() const
+{
+ return _xmin;
+}
+
+void QFxDrag::setXmin(int m)
+{
+ _xmin = m;
+}
+
+/*!
+ \property QFxDrag::xmax
+ \brief the maximum x position for the target
+
+ If x-axis dragging is enabled, xmax limits how far to the right the target can be dragged. If x-axis dragging is not enabled, this property has no effect.
+*/
+int QFxDrag::xmax() const
+{
+ return _xmax;
+}
+
+void QFxDrag::setXmax(int m)
+{
+ _xmax = m;
+}
+
+/*!
+ \property QFxDrag::ymin
+ \brief the minimum y position for the target
+
+ If y-axis dragging is enabled, ymin limits how far up the target can be dragged. If y-axis dragging is not enabled, this property has no effect.
+*/
+int QFxDrag::ymin() const
+{
+ return _ymin;
+}
+
+void QFxDrag::setYmin(int m)
+{
+ _ymin = m;
+}
+
+/*!
+ \property QFxDrag::ymax
+ \brief the maximum y position for the target
+
+ If y-axis dragging is enabled, ymax limits how far down the target can be dragged. If y-axis dragging is not enabled, this property has no effect.
+*/
+int QFxDrag::ymax() const
+{
+ return _ymax;
+}
+
+void QFxDrag::setYmax(int m)
+{
+ _ymax = m;
+}
+
+/*!
+ \qmlclass MouseRegion
+ \brief The MouseRegion item enables simple mouse handling.
+ \inherits Item
+
+ A MouseRegion is typically used in conjunction with a visible item,
+ where the MouseRegion effectively 'proxies' mouse handling for that
+ item. For example, we can put a MouseRegion in a Rect that changes
+ the Rect color to red when clicked:
+ \snippet doc/src/snippets/declarative/mouseregion.qml 0
+
+ Many MouseRegion signals pass a \l {MouseEvent}{mouse} parameter that contains
+ additional information about the mouse event, such as the position, button,
+ and any key modifiers.
+
+ Below we have the previous
+ example extended so as to give a different color when you right click.
+ \snippet doc/src/snippets/declarative/mouseregion.qml 1
+
+ For basic key handling, see \l KeyActions.
+
+ MouseRegion is an invisible item: it is never painted.
+
+ \sa MouseEvent
+*/
+
+/*!
+ \qmlsignal MouseRegion::onEntered
+
+ This handler is called when the mouse enters the mouse region.
+
+ \warning This handler is not yet implemented.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onExited
+
+ This handler is called when the mouse exists the mouse region.
+
+ \warning This handler is not yet implemented.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onReenteredWhilePressed
+
+ This handler is called when the mouse reenters the mouse region while pressed.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onExitedWhilePressed
+
+ This handler is called when the mouse exists the mouse region while pressed.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onPositionChanged(mouse)
+
+ This handler is called when the mouse position changes.
+
+ The \l {MouseEvent}{mouse} parameter provides information about the mouse, including the x and y
+ position, and any buttons currently pressed.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onClicked(mouse)
+
+ This handler is called when there is a click. A click is defined as a press followed by a release,
+ both inside the MouseRegion (pressing, moving outside the MouseRegion, and then moving back inside and
+ releasing is also considered a click).
+
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click wasHeld.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onPressed(mouse)
+
+ This handler is called when there is a press.
+ The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
+ position and which button was pressed.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onReleased(mouse)
+
+ This handler is called when there is a release.
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click wasHeld.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onPressAndHold(mouse)
+
+ This handler is called when there is a long press (currently 800ms).
+ The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
+ position of the press, and which button is pressed.
+*/
+
+/*!
+ \qmlsignal MouseRegion::onDoubleClicked(mouse)
+
+ This handler is called when there is a double-click (a press followed by a release followed by a press).
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click wasHeld.
+*/
+
+QML_DEFINE_TYPE(QFxMouseRegion,MouseRegion);
+
+/*!
+ \internal
+ \class QFxMouseRegion
+ \brief The QFxMouseRegion class provides a simple mouse handling abstraction for use within Qml.
+
+ \ingroup group_coreitems
+
+ All QFxItem derived classes can do mouse handling but the QFxMouseRegion class exposes mouse
+ handling data as properties and tracks flicking and dragging of the mouse.
+
+ A QFxMouseRegion object can be instantiated in Qml using the tag \l MouseRegion.
+ */
+QFxMouseRegion::QFxMouseRegion(QFxItem *parent)
+ : QFxItem(*(new QFxMouseRegionPrivate), parent)
+{
+ Q_D(QFxMouseRegion);
+ d->init();
+}
+
+QFxMouseRegion::QFxMouseRegion(QFxMouseRegionPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxMouseRegion);
+ d->init();
+}
+
+QFxMouseRegion::~QFxMouseRegion()
+{
+}
+
+/*!
+ \qmlproperty int MouseRegion::mouseX
+ \qmlproperty int MouseRegion::mouseY
+
+ The coordinates of the mouse while pressed. The coordinates are relative to the item that was pressed.
+*/
+int QFxMouseRegion::mouseX() const
+{
+ Q_D(const QFxMouseRegion);
+ return int(d->lastPos.x());
+}
+
+int QFxMouseRegion::mouseY() const
+{
+ Q_D(const QFxMouseRegion);
+ return int(d->lastPos.y());
+}
+
+/*!
+ \qmlproperty bool MouseRegion::enabled
+ This property holds whether the item accepts mouse events.
+*/
+bool QFxMouseRegion::isEnabled() const
+{
+ Q_D(const QFxMouseRegion);
+ return d->absorb;
+}
+
+void QFxMouseRegion::setEnabled(bool a)
+{
+ Q_D(QFxMouseRegion);
+ d->absorb = a;
+}
+
+void QFxMouseRegion::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ d->moved = false;
+ if (!d->absorb)
+ QFxItem::mousePressEvent(event);
+ else {
+ if (!d->inside) {
+ d->inside = true;
+ emit hoveredChanged();
+ }
+ d->longPress = false;
+ d->saveEvent(event);
+ d->dragX = drag()->axis().contains(QLatin1String("x"));
+ d->dragY = drag()->axis().contains(QLatin1String("y"));
+ d->dragged = false;
+ d->start = event->pos();
+ d->startScene = event->scenePos();
+ // ### we should only start timer if pressAndHold is connected to (but connectNotify doesn't work)
+ d->pressAndHoldTimer.start(PressAndHoldDelay, this);
+ setKeepMouseGrab(false);
+ setPressed(true);
+ event->accept();
+ }
+}
+
+void QFxMouseRegion::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ if (!d->absorb) {
+ QFxItem::mouseMoveEvent(event);
+ return;
+ }
+
+ d->saveEvent(event);
+
+ // ### we should skip this if these signals aren't used
+ const QRect &bounds = itemBoundingRect();
+ bool contains = bounds.contains(d->lastPos.toPoint());
+ if (d->inside && !contains) {
+ d->inside = false;
+ emit hoveredChanged();
+ emit exitedWhilePressed();
+ } else if (!d->inside && contains) {
+ d->inside = true;
+ emit hoveredChanged();
+ emit reenteredWhilePressed();
+ }
+
+ if (drag()->target()) {
+ if (!d->moved) {
+ if (d->dragX) d->startX = int(drag()->target()->x()); //### change startX and startY to qreal?
+ if (d->dragY) d->startY = int(drag()->target()->y());
+ }
+
+ QPointF startLocalPos;
+ QPointF curLocalPos;
+ if (drag()->target()->parent()) {
+ startLocalPos = drag()->target()->parent()->mapFromScene(d->startScene);
+ curLocalPos = drag()->target()->parent()->mapFromScene(event->scenePos());
+ } else {
+ startLocalPos = d->startScene;
+ curLocalPos = event->scenePos();
+ }
+
+ int dx = int(qAbs(curLocalPos.x() - startLocalPos.x()));
+ int dy = int(qAbs(curLocalPos.y() - startLocalPos.y()));
+ if ((d->dragX && !(dx < DragThreshold)) || (d->dragY && !(dy < DragThreshold)))
+ d->dragged = true;
+ if (!keepMouseGrab()) {
+ if ((!d->dragY && dy < DragThreshold && d->dragX && dx > DragThreshold)
+ || (!d->dragX && dx < DragThreshold && d->dragY && dy > DragThreshold)
+ || (d->dragX && d->dragY)) {
+ setKeepMouseGrab(true);
+ }
+ }
+
+ if (d->dragX) {
+ qreal x = (curLocalPos.x() - startLocalPos.x()) + d->startX;
+ if (x < drag()->xmin())
+ x = drag()->xmin();
+ else if (x > drag()->xmax())
+ x = drag()->xmax();
+ drag()->target()->setX(x);
+ }
+ if (d->dragY) {
+ qreal y = (curLocalPos.y() - startLocalPos.y()) + d->startY;
+ if (y < drag()->ymin())
+ y = drag()->ymin();
+ else if (y > drag()->ymax())
+ y = drag()->ymax();
+ drag()->target()->setY(y);
+ }
+ }
+ d->moved = true;
+ QFxMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
+ emit positionChanged(&me);
+ event->accept();
+}
+
+
+void QFxMouseRegion::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ if (!d->absorb)
+ QFxItem::mouseReleaseEvent(event);
+ else {
+ d->saveEvent(event);
+ setPressed(false);
+ //d->inside = false;
+ //emit hoveredChanged();
+ event->accept();
+ }
+}
+
+void QFxMouseRegion::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ if (!d->absorb)
+ QFxItem::mouseDoubleClickEvent(event);
+ else {
+ //d->inside = true;
+ //emit hoveredChanged();
+ d->saveEvent(event);
+ setPressed(true);
+ QFxMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
+ emit this->doubleClicked(&me);
+ event->accept();
+ }
+}
+
+void QFxMouseRegion::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ if (!d->absorb)
+ QFxItem::hoverEnterEvent(event);
+ else {
+ setHovered(true);
+ emit entered();
+ }
+}
+
+void QFxMouseRegion::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ if (!d->absorb)
+ QFxItem::hoverLeaveEvent(event);
+ else {
+ setHovered(false);
+ emit exited();
+ }
+}
+
+void QFxMouseRegion::mouseUngrabEvent()
+{
+ Q_D(QFxMouseRegion);
+ if (d->pressed) {
+ // if our mouse grab has been removed (probably by Flickable), fix our
+ // state
+ d->pressed = false;
+ //d->inside = false;
+ setKeepMouseGrab(false);
+ emit pressedChanged();
+ //emit hoveredChanged();
+ }
+}
+
+void QFxMouseRegion::timerEvent(QTimerEvent *event)
+{
+ Q_D(QFxMouseRegion);
+ if (event->timerId() == d->pressAndHoldTimer.timerId()) {
+ d->pressAndHoldTimer.stop();
+ if (d->pressed && d->dragged == false && d->inside == true) {
+ d->longPress = true;
+ QFxMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
+ emit pressAndHold(&me);
+ }
+ }
+}
+
+/*!
+ \qmlproperty bool MouseRegion::containsMouse
+ This property holds whether the mouse is currently inside the mouse region.
+
+ \warning This property is only partially implemented -- it is only valid when the mouse is pressed, and not for hover events.
+*/
+bool QFxMouseRegion::hovered()
+{
+ Q_D(QFxMouseRegion);
+ return d->hovered || d->inside;
+}
+
+/*!
+ \qmlproperty bool MouseRegion::pressed
+ This property holds whether the mouse region is currently pressed.
+*/
+bool QFxMouseRegion::pressed()
+{
+ Q_D(QFxMouseRegion);
+ return d->pressed;
+}
+
+void QFxMouseRegion::setHovered(bool h)
+{
+ Q_D(QFxMouseRegion);
+ if (d->hovered != h) {
+ d->hovered = h;
+ emit hoveredChanged();
+ }
+}
+
+void QFxMouseRegion::setPressed(bool p)
+{
+ Q_D(QFxMouseRegion);
+ bool isclick = d->pressed == true && p == false && d->dragged == false && d->inside == true;
+
+ if (d->pressed != p) {
+ d->pressed = p;
+ QFxMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
+ if (d->pressed) {
+ emit positionChanged(&me);
+ emit pressed(&me);
+ } else {
+ emit released(&me);
+ if (isclick)
+ emit clicked(&me);
+ }
+
+ emit pressedChanged();
+ }
+}
+
+/*!
+ \property QFxMouseRegion::drag
+ \brief The current drag being performed on the Mouse Region.
+*/
+QFxDrag *QFxMouseRegion::drag()
+{
+ Q_D(QFxMouseRegion);
+ return &(d->drag);
+}
+
+/*!
+ \qmlproperty Item MouseRegion::drag.target
+ \qmlproperty string MouseRegion::drag.axis
+ \qmlproperty int MouseRegion::drag.xmin
+ \qmlproperty int MouseRegion::drag.xmax
+ \qmlproperty int MouseRegion::drag.ymin
+ \qmlproperty int MouseRegion::drag.ymax
+
+ drag provides a convenient way to make an item draggable.
+
+ \list
+ \i \c target specifies the item to drag.
+ \i \c axis specifies whether dragging can be done horizontally (x), vertically (y), or both (x,y)
+ \i the min and max properties limit how far the target can be dragged along the corresponding axes.
+ \endlist
+
+ The following example uses drag to reduce the opacity of an image as it moves to the right:
+ \snippet doc/src/snippets/declarative/drag.qml 0
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxmouseregion.h b/src/declarative/fx/qfxmouseregion.h
new file mode 100644
index 0000000..2ba4a50
--- /dev/null
+++ b/src/declarative/fx/qfxmouseregion.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXMOUSEREGION_H
+#define QFXMOUSEREGION_H
+
+#include <qfxitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QFxDrag : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QFxItem *target READ target WRITE setTarget)
+ Q_PROPERTY(QString axis READ axis WRITE setAxis)
+ Q_PROPERTY(int xmin READ xmin WRITE setXmin)
+ Q_PROPERTY(int xmax READ xmax WRITE setXmax)
+ Q_PROPERTY(int ymin READ ymin WRITE setYmin)
+ Q_PROPERTY(int ymax READ ymax WRITE setYmax)
+public:
+ QFxDrag(QObject *parent=0);
+ ~QFxDrag();
+
+ QFxItem *target() const;
+ void setTarget(QFxItem *);
+ QString axis() const;
+ void setAxis(const QString &);
+ int xmin() const;
+ void setXmin(int);
+ int xmax() const;
+ void setXmax(int);
+ int ymin() const;
+ void setYmin(int);
+ int ymax() const;
+ void setYmax(int);
+
+private:
+ QFxItem *_target;
+ QString _axis;
+ int _xmin;
+ int _xmax;
+ int _ymin;
+ int _ymax;
+ Q_DISABLE_COPY(QFxDrag)
+};
+QML_DECLARE_TYPE(QFxDrag);
+
+class QFxMouseEvent;
+class QFxMouseRegionPrivate;
+class Q_DECLARATIVE_EXPORT QFxMouseRegion : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int mouseX READ mouseX NOTIFY positionChanged)
+ Q_PROPERTY(int mouseY READ mouseY NOTIFY positionChanged)
+ Q_PROPERTY(bool containsMouse READ hovered NOTIFY hoveredChanged)
+ Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
+ Q_PROPERTY(QFxDrag *drag READ drag)
+public:
+ QFxMouseRegion(QFxItem *parent=0);
+ ~QFxMouseRegion();
+
+ int mouseX() const;
+ int mouseY() const;
+
+ bool isEnabled() const;
+ void setEnabled(bool);
+
+ bool hovered();
+ bool pressed();
+
+ void setHovered(bool);
+ void setPressed(bool);
+
+ QFxDrag *drag();
+
+Q_SIGNALS:
+ void hoveredChanged();
+ void pressedChanged();
+ void positionChanged(QFxMouseEvent *mouse);
+
+ void pressed(QFxMouseEvent *mouse);
+ void pressAndHold(QFxMouseEvent *mouse);
+ void released(QFxMouseEvent *mouse);
+ void clicked(QFxMouseEvent *mouse);
+ void doubleClicked(QFxMouseEvent *mouse);
+ void entered();
+ void exited();
+ void exitedWhilePressed();
+ void reenteredWhilePressed();
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+ void mouseUngrabEvent();
+ void timerEvent(QTimerEvent *event);
+
+private:
+ void handlePress();
+ void handleRelease();
+
+protected:
+ QFxMouseRegion(QFxMouseRegionPrivate &dd, QFxItem *parent);
+
+private:
+ Q_DISABLE_COPY(QFxMouseRegion)
+ Q_DECLARE_PRIVATE(QFxMouseRegion)
+};
+QML_DECLARE_TYPE(QFxMouseRegion);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXMOUSEREGION_H
diff --git a/src/declarative/fx/qfxmouseregion_p.h b/src/declarative/fx/qfxmouseregion_p.h
new file mode 100644
index 0000000..e444bf2
--- /dev/null
+++ b/src/declarative/fx/qfxmouseregion_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXMOUSEREGION_P_H
+#define QFXMOUSEREGION_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 "qdatetime.h"
+#include "qbasictimer.h"
+#include "qgraphicssceneevent.h"
+#include "qfxitem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QFxMouseRegionPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxMouseRegion)
+
+public:
+ QFxMouseRegionPrivate()
+ : absorb(true), hovered(false), inside(true), pressed(false), longPress(false), drag(0)
+ {
+ }
+
+ void init()
+ {
+ Q_Q(QFxMouseRegion);
+ q->setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
+ q->setOptions(QSimpleCanvasItem::HoverEvents | QSimpleCanvasItem::MouseEvents);
+ }
+
+ void saveEvent(QGraphicsSceneMouseEvent *event) {
+ lastPos = event->pos();
+ lastButton = event->button();
+ lastButtons = event->buttons();
+ lastModifiers = event->modifiers();
+ }
+
+ bool absorb : 1;
+ bool hovered : 1;
+ bool inside : 1;
+ bool pressed : 1;
+ bool longPress : 1;
+ bool moved : 1;
+ bool dragX : 1;
+ bool dragY : 1;
+ bool dragged : 1;
+ QFxDrag drag;
+ QPointF start;
+ QPointF startScene;
+ int startX;
+ int startY;
+ QPointF lastPos;
+ Qt::MouseButton lastButton;
+ Qt::MouseButtons lastButtons;
+ Qt::KeyboardModifiers lastModifiers;
+ QBasicTimer pressAndHoldTimer;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFXMOUSEREGION_P_H
diff --git a/src/declarative/fx/qfxpainteditem.cpp b/src/declarative/fx/qfxpainteditem.cpp
new file mode 100644
index 0000000..4d2e327
--- /dev/null
+++ b/src/declarative/fx/qfxpainteditem.cpp
@@ -0,0 +1,344 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxpainteditem.h"
+#include "qfxpainteditem_p.h"
+
+#include <QDebug>
+#include <QPen>
+#include <QFile>
+#include <QEvent>
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <QtOpenGL/qglframebufferobject.h>
+#include <glsave.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QFxPaintedItem
+ \brief The QFxPaintedItem class is an abstract base class for QFxView items that want cached painting.
+ \ingroup group_coreitems
+
+ This is a convenience class for implementing items that paint their contents
+ using a QPainter. The contents of the item are are cached behind the scenes.
+ The dirtyCache() function should be called if the contents change to
+ ensure the cache is refreshed the next time painting occurs.
+
+ To subclass QFxPaintedItem, you must reimplement drawContents() to draw
+ the contents of the item.
+*/
+
+/*!
+ \fn void QFxPaintedItem::drawContents(QPainter *painter, const QRect &rect)
+
+ This function is called when the cache needs to be refreshed. When
+ sub-classing QFxPaintedItem this function should be implemented so as to
+ paint the contents of the item using the given \a painter for the
+ area of the contents specified by \a rect.
+*/
+
+/*!
+ \property QFxPaintedItem::contentsSize
+ \brief The size of the contents
+
+ The contents size is the size of the item in regards to how it is painted
+ using the drawContents() function. This is distinct from the size of the
+ item in regards to height() and width().
+*/
+
+/*!
+ \property QFxPaintedItem::smooth
+ \brief Setting for whether smooth scaling is enabled.
+*/
+
+/*!
+ Marks areas of the cache that intersect with the given \a rect as dirty and
+ in need of being refreshed.
+
+ \sa clearCache()
+*/
+void QFxPaintedItem::dirtyCache(const QRect& rect)
+{
+ Q_D(QFxPaintedItem);
+ for (int i=0; i < d->imagecache.count(); ) {
+ if (d->imagecache[i]->area.intersects(rect)) {
+ d->imagecache.removeAt(i);
+ } else {
+ ++i;
+ }
+ }
+}
+
+/*!
+ Marks the entirety of the contents cache as dirty.
+
+ \sa dirtyCache()
+*/
+void QFxPaintedItem::clearCache()
+{
+ Q_D(QFxPaintedItem);
+ qDeleteAll(d->imagecache);
+ d->imagecache.clear();
+}
+
+/*!
+ Returns if smooth scaling of the cache contents is enabled.
+
+ \sa setSmooth()
+*/
+bool QFxPaintedItem::isSmooth() const
+{
+ Q_D(const QFxPaintedItem);
+ return d->smooth;
+}
+
+/*!
+ Returns the size of the contents.
+
+ \sa setContentsSize()
+*/
+QSize QFxPaintedItem::contentsSize() const
+{
+ Q_D(const QFxPaintedItem);
+ return d->contentsSize;
+}
+
+/*!
+ If \a smooth is true sets the image item to enable smooth scaling of
+ the cache contents.
+
+ \sa isSmooth()
+*/
+void QFxPaintedItem::setSmooth(bool smooth)
+{
+ Q_D(QFxPaintedItem);
+ if (d->smooth == smooth) return;
+ d->smooth = smooth;
+ clearCache();
+ update();
+}
+
+/*!
+ Sets the size of the contents to the given \a size.
+
+ \sa contentsSize()
+*/
+void QFxPaintedItem::setContentsSize(const QSize &size)
+{
+ Q_D(QFxPaintedItem);
+ if (d->contentsSize == size) return;
+ d->contentsSize = size;
+ clearCache();
+ update();
+}
+
+/*!
+ Constructs a new QFxPaintedItem with the given \a parent.
+*/
+QFxPaintedItem::QFxPaintedItem(QFxItem *parent)
+ : QFxItem(*(new QFxPaintedItemPrivate), parent)
+{
+ init();
+}
+
+/*!
+ \internal
+ Constructs a new QFxPaintedItem with the given \a parent and
+ initialized private data member \a dd.
+*/
+QFxPaintedItem::QFxPaintedItem(QFxPaintedItemPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ init();
+}
+
+/*!
+ Destroys the image item.
+*/
+QFxPaintedItem::~QFxPaintedItem()
+{
+}
+
+/*!
+ \internal
+*/
+void QFxPaintedItem::init()
+{
+ connect(this,SIGNAL(widthChanged()),this,SLOT(clearCache()));
+ connect(this,SIGNAL(heightChanged()),this,SLOT(clearCache()));
+ connect(this,SIGNAL(visibleChanged()),this,SLOT(clearCache()));
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+/*!
+ \reimp
+*/
+void QFxPaintedItem::paintContents(QPainter &p)
+#elif defined(QFX_RENDER_OPENGL)
+/*!
+ \reimp
+*/
+void QFxPaintedItem::paintGLContents(GLPainter &p)
+#else
+#error "What render?"
+#endif
+{
+ Q_D(QFxPaintedItem);
+ const QRect content(QPoint(0,0),d->contentsSize);
+ if (content.width() <= 0 || content.height() <= 0)
+ return;
+
+#if defined(QFX_RENDER_QPAINTER)
+ bool oldAntiAliasing = p.testRenderHint(QPainter::Antialiasing);
+ bool oldSmoothPixmap = p.testRenderHint(QPainter::SmoothPixmapTransform);
+ if (d->smooth) {
+ p.setRenderHints(QPainter::Antialiasing, true);
+ p.setRenderHints(QPainter::SmoothPixmapTransform, true);
+ }
+ QRectF clipf = p.clipRegion().boundingRect();
+ if (clipf.isEmpty())
+ clipf = mapToScene(content); // ### Inefficient: Maps toScene and then fromScene
+ else
+ clipf = mapToScene(clipf);
+
+#elif defined(QFX_RENDER_OPENGL2)
+ p.useTextureShader();
+ const QRectF clipf = p.sceneClipRect;
+
+#elif defined(QFX_RENDER_OPENGL1)
+ p.useTextureShader();
+ const QRectF clipf = p.sceneClipRect;
+#endif
+
+ const QRect clip = mapFromScene(clipf).toRect();
+
+ QRegion topaint(clip);
+ topaint &= content;
+ QRegion uncached(content);
+
+#if defined(QFX_RENDER_OPENGL2)
+ glEnableVertexAttribArray(SingleTextureShader::Vertices);
+ glEnableVertexAttribArray(SingleTextureShader::TextureCoords);
+#elif defined(QFX_RENDER_OPENGL1)
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+#endif
+
+ int cachesize=0;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ QRect area = d->imagecache[i]->area;
+ if (topaint.contains(area)) {
+ QRectF target(area.x(), area.y(), area.width(), area.height());
+ p.drawImage(target.toRect(), d->imagecache[i]->image);
+ topaint -= area;
+ d->imagecache[i]->age=0;
+ } else {
+ d->imagecache[i]->age++;
+ }
+ cachesize += area.width()*area.height();
+ uncached -= area;
+ }
+
+ if (!topaint.isEmpty()) {
+ // Find a sensible larger area, otherwise will paint lots of tiny images.
+ QRect biggerrect = topaint.boundingRect().adjusted(-64,-64,128,128);
+ cachesize += biggerrect.width() * biggerrect.height();
+ while (d->imagecache.count() && cachesize > d->max_imagecache_size) {
+ int oldest=-1;
+ int age=-1;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ int a = d->imagecache[i]->age;
+ if (a > age) {
+ oldest = i;
+ age = a;
+ }
+ }
+ cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
+ uncached += d->imagecache[oldest]->area;
+ d->imagecache.removeAt(oldest);
+ }
+ const QRegion bigger = QRegion(biggerrect) & uncached;
+ const QVector<QRect> rects = bigger.rects();
+ for (int i = 0; i < rects.count(); ++i) {
+ const QRect &r = rects.at(i);
+#if defined(QFX_RENDER_QPAINTER)
+ QImage img(r.size(),QImage::Format_ARGB32_Premultiplied);
+#else
+ QImage img(r.size(),QImage::Format_ARGB32);
+#endif
+ img.fill(0);
+ {
+ QPainter qp(&img);
+ qp.translate(-r.x(),-r.y());
+ drawContents(&qp, r);
+ }
+ QFxPaintedItemPrivate::ImageCacheItem *newitem = new QFxPaintedItemPrivate::ImageCacheItem;
+ newitem->area = r;
+#if defined(QFX_RENDER_QPAINTER)
+ newitem->image = QSimpleCanvasConfig::Image(QSimpleCanvasConfig::toImage(img));
+#else
+ newitem->image.setImage(img);
+#endif
+ d->imagecache.append(newitem);
+ QRectF target(r.x(), r.y(), r.width(), r.height());
+ p.drawImage(target.toRect(), newitem->image);
+ }
+ }
+#if defined(QFX_RENDER_OPENGL2)
+ glDisableVertexAttribArray(SingleTextureShader::Vertices);
+ glDisableVertexAttribArray(SingleTextureShader::TextureCoords);
+#elif defined(QFX_RENDER_OPENGL1)
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+#endif
+#if defined(QFX_RENDER_QPAINTER)
+ if (d->smooth) {
+ p.setRenderHints(QPainter::Antialiasing, oldAntiAliasing);
+ p.setRenderHints(QPainter::SmoothPixmapTransform, oldSmoothPixmap);
+ }
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxpainteditem.h b/src/declarative/fx/qfxpainteditem.h
new file mode 100644
index 0000000..015a035
--- /dev/null
+++ b/src/declarative/fx/qfxpainteditem.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXIMAGEITEM_H
+#define QFXIMAGEITEM_H
+
+#include <qfxglobal.h>
+#include <qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QFxPaintedItemPrivate;
+class Q_DECLARATIVE_EXPORT QFxPaintedItem : public QFxItem
+{
+ Q_OBJECT
+public:
+ QFxPaintedItem(QFxItem *parent=0);
+ ~QFxPaintedItem();
+
+ Q_PROPERTY(QSize contentsSize READ contentsSize WRITE setContentsSize);
+ Q_PROPERTY(bool smooth READ isSmooth WRITE setSmooth);
+
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &painter);
+#elif defined(QFX_RENDER_OPENGL)
+ void paintGLContents(GLPainter &);
+#endif
+
+ bool isSmooth() const;
+ QSize contentsSize() const;
+
+ void setSmooth(bool);
+ void setContentsSize(const QSize &);
+protected:
+ QFxPaintedItem(QFxPaintedItemPrivate &dd, QFxItem *parent);
+
+ virtual void drawContents(QPainter *p, const QRect &) = 0;
+
+protected Q_SLOTS:
+ void dirtyCache(const QRect &);
+ void clearCache();
+
+private:
+ void init();
+ Q_DISABLE_COPY(QFxPaintedItem)
+ Q_DECLARE_PRIVATE(QFxPaintedItem)
+};
+QML_DECLARE_TYPE(QFxPaintedItem);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxpainteditem_p.h b/src/declarative/fx/qfxpainteditem_p.h
new file mode 100644
index 0000000..b0432ac
--- /dev/null
+++ b/src/declarative/fx/qfxpainteditem_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXIMAGEITEM_P_H
+#define QFXIMAGEITEM_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 "qfxitem_p.h"
+#include <qsimplecanvas.h>
+
+#if defined(QFX_RENDER_OPENGL)
+#include "gltexture.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QFxPaintedItemPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxPaintedItem)
+
+public:
+ QFxPaintedItemPrivate()
+ : max_imagecache_size(1000*1000), smooth(false)
+ {
+ }
+
+ struct ImageCacheItem {
+ ImageCacheItem() : age(0) {}
+ ~ImageCacheItem() { }
+ int age;
+ QRect area;
+#if defined(QFX_RENDER_QPAINTER)
+ QSimpleCanvasConfig::Image image;
+#else
+ GLTexture image;
+#endif
+ };
+
+ QList<ImageCacheItem*> imagecache;
+
+ const int max_imagecache_size;
+ bool smooth;
+ QSize contentsSize;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/fx/qfxparticles.cpp b/src/declarative/fx/qfxparticles.cpp
new file mode 100644
index 0000000..1aaf256
--- /dev/null
+++ b/src/declarative/fx/qfxparticles.cpp
@@ -0,0 +1,1120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxitem_p.h"
+#if defined(QFX_RENDER_OPENGL)
+#include "gltexture.h"
+#endif
+
+#include <stdlib.h>
+#include <math.h>
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#define M_PI_2 (M_PI / 2.)
+#endif
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
+#include <qfxpixmap.h>
+#include <qfxperf.h>
+#include <private/qmlanimation_p.h>
+
+#include "qfxparticles.h"
+
+
+QT_BEGIN_NAMESPACE
+#define PI_SQR 9.8696044
+// parabolic approximation
+inline qreal fastSin(qreal theta)
+{
+ const qreal b = 4 / M_PI;
+ const qreal c = -4 / PI_SQR;
+
+ qreal y = b * theta + c * theta * qAbs(theta);
+ return y;
+}
+
+inline qreal fastCos(qreal theta)
+{
+ theta += M_PI_2;
+ if (theta > M_PI)
+ theta -= 2 * M_PI;
+
+ return fastSin(theta);
+}
+
+class QFxParticle
+{
+public:
+ QFxParticle(int time) : lifeSpan(1000), fadeOutAge(800)
+ , opacity(0), birthTime(time), x_velocity(0), y_velocity(0)
+ , state(FadeIn), data(0)
+ {
+ }
+
+ int lifeSpan;
+ int fadeOutAge;
+ qreal x;
+ qreal y;
+ qreal opacity;
+ int birthTime;
+ qreal x_velocity;
+ qreal y_velocity;
+ enum State { FadeIn, Solid, FadeOut };
+ State state;
+ void *data;
+};
+
+//---------------------------------------------------------------------------
+
+QML_DEFINE_TYPE(QFxParticleMotion,ParticleMotion);
+
+/*!
+ \class QFxParticleMotion
+ \ingroup group_effects
+ \brief The QFxParticleMotion class is the base class for particle motion.
+
+ This class causes the particles to remain static.
+*/
+
+/*!
+ Constructs a QFxParticleMotion with parent object \a parent.
+*/
+QFxParticleMotion::QFxParticleMotion(QObject *parent) :
+ QObject(parent)
+{
+}
+
+/*!
+ Move the \a particle to its new position. \a interval is the number of
+ milliseconds elapsed since it was last moved.
+*/
+void QFxParticleMotion::advance(QFxParticle &particle, int interval)
+{
+ Q_UNUSED(particle);
+ Q_UNUSED(interval);
+}
+
+/*!
+ The \a particle has just been created. Some motion strategies require
+ additional state information. This can be allocated by this function.
+*/
+void QFxParticleMotion::created(QFxParticle &particle)
+{
+ Q_UNUSED(particle);
+}
+
+/*!
+ The \a particle is about to be destroyed. Any additional memory
+ that has been allocated for the particle should be freed.
+*/
+void QFxParticleMotion::destroy(QFxParticle &particle)
+{
+ Q_UNUSED(particle);
+}
+
+/*!
+ \qmlclass ParticleMotionLinear
+ \brief The ParticleMotionLinear object moves particles linearly.
+
+ \sa Particles
+*/
+
+/*!
+ \internal
+ \class QFxParticleMotionLinear
+ \ingroup group_effects
+ \brief The QFxParticleMotionLinear class moves the particles linearly.
+*/
+
+QML_DEFINE_TYPE(QFxParticleMotionLinear,ParticleMotionLinear);
+
+void QFxParticleMotionLinear::advance(QFxParticle &p, int interval)
+{
+ p.x += interval * p.x_velocity;
+ p.y += interval * p.y_velocity;
+}
+
+/*!
+ \qmlclass ParticleMotionGravity
+ \brief The ParticleMotionGravity object moves particles towards a point.
+
+ \sa Particles
+*/
+
+/*!
+ \internal
+ \class QFxParticleMotionGravity
+ \ingroup group_effects
+ \brief The QFxParticleMotionGravity class moves the particles towards a point.
+*/
+
+QML_DEFINE_TYPE(QFxParticleMotionGravity,ParticleMotionGravity);
+
+/*!
+ \qmlproperty int ParticleMotionGravity::xattractor
+ \qmlproperty int ParticleMotionGravity::yattractor
+ These properties hold the x and y coordinates of the point attracting the particles.
+*/
+
+/*!
+ \qmlproperty int ParticleMotionGravity::acceleration
+ This property holds the acceleration to apply to the particles.
+*/
+
+/*!
+ \property QFxParticleMotionGravity::xattractor
+ \brief the x coordinate of the point attracting the particles.
+*/
+
+/*!
+ \property QFxParticleMotionGravity::yattractor
+ \brief the y coordinate of the point attracting the particles.
+*/
+
+/*!
+ \property QFxParticleMotionGravity::acceleration
+ \brief the acceleration to apply to the particles.
+*/
+
+void QFxParticleMotionGravity::advance(QFxParticle &p, int interval)
+{
+ qreal xdiff = p.x - _xAttr;
+ qreal ydiff = p.y - _yAttr;
+
+ qreal xcomp = xdiff / (xdiff + ydiff);
+ qreal ycomp = ydiff / (xdiff + ydiff);
+
+ p.x_velocity += xcomp * _accel * interval;
+ p.y_velocity += ycomp * _accel * interval;
+
+ p.x += interval * p.x_velocity;
+ p.y += interval * p.y_velocity;
+}
+
+/*!
+ \qmlclass ParticleMotionWander
+ \brief The ParticleMotionWander object moves particles in a somewhat random fashion.
+
+ The particles will continue roughly in the original direction, however will randomly
+ drift to each side.
+
+ The code below produces an effect similar to falling snow.
+
+ \qml
+Rect {
+ width: 240
+ height: 320
+ color: "black"
+
+ Particles {
+ y: 0
+ width: parent.width
+ height: 30
+ source: "star.png"
+ lifeSpan: 5000
+ count: 50
+ angle: 70
+ angleDeviation: 36
+ velocity: 30
+ velocityDeviation: 10
+ ParticleMotionWander {
+ xvariance: 30
+ pace: 100
+ }
+ }
+}
+ \endqml
+
+ \sa Particles
+*/
+
+/*!
+ \internal
+ \class QFxParticleMotionWander
+ \ingroup group_effects
+ \brief The QFxParticleMotionWander class moves particles in a somewhat random fashion.
+
+ The particles will continue roughly in the original direction, however will randomly
+ drift to each side.
+*/
+
+/*!
+ \qmlproperty int QFxParticleMotionWander::xvariance
+ \qmlproperty int QFxParticleMotionWander::yvariance
+
+ These properties set the amount to wander in the x and y directions.
+*/
+
+/*!
+ \qmlproperty int QFxParticleMotionWander::pace
+ This property holds how quickly the paricles will move from side to side.
+*/
+
+QML_DEFINE_TYPE(QFxParticleMotionWander,ParticleMotionWander);
+
+void QFxParticleMotionWander::advance(QFxParticle &p, int interval)
+{
+ if (!particles)
+ particles = qobject_cast<QFxParticles*>(parent());
+ if (particles) {
+ Data *d = (Data*)p.data;
+ if (_xvariance != 0.) {
+ qreal xdiff = p.x_velocity - d->x_targetV;
+ if ((xdiff > d->x_peak && d->x_var > 0.0) || (xdiff < -d->x_peak && d->x_var < 0.0)) {
+ d->x_var = -d->x_var;
+ d->x_peak = _xvariance + _xvariance * qreal(rand()) / RAND_MAX;
+ }
+ p.x_velocity += d->x_var * interval;
+ }
+ p.x += interval * p.x_velocity;
+
+ if (_yvariance != 0.) {
+ qreal ydiff = p.y_velocity - d->y_targetV;
+ if ((ydiff > d->y_peak && d->y_var > 0.0) || (ydiff < -d->y_peak && d->y_var < 0.0)) {
+ d->y_var = -d->y_var;
+ d->y_peak = _yvariance + _yvariance * qreal(rand()) / RAND_MAX;
+ }
+ p.y_velocity += d->y_var * interval;
+ }
+ p.y += interval * p.y_velocity;
+ }
+}
+
+void QFxParticleMotionWander::created(QFxParticle &p)
+{
+ if (!p.data) {
+ Data *d = new Data;
+ p.data = (void*)d;
+ d->x_targetV = p.x_velocity;
+ d->y_targetV = p.y_velocity;
+ d->x_peak = _xvariance;
+ d->y_peak = _yvariance;
+ d->x_var = _pace * qreal(rand()) / RAND_MAX / 1000.0;
+ d->y_var = _pace * qreal(rand()) / RAND_MAX / 1000.0;
+ }
+}
+
+void QFxParticleMotionWander::destroy(QFxParticle &p)
+{
+ if (p.data)
+ delete (Data*)p.data;
+}
+
+//---------------------------------------------------------------------------
+class QFxParticlesPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxParticles)
+public:
+ QFxParticlesPrivate()
+ : count(1), lifeSpan(1000), lifeSpanDev(1000), fadeInDur(200), fadeOutDur(300)
+ , angle(0), angleDev(0), velocity(0), velocityDev(0)
+ , addParticleTime(0), addParticleCount(0), lastAdvTime(0), stream(false), streamDelay(0)
+ , emitting(true), motion(0), clock(this)
+#if defined(QFX_RENDER_OPENGL)
+ , texDirty(true)
+#endif
+ {
+ }
+
+ ~QFxParticlesPrivate()
+ {
+ }
+
+ void init() {}
+ void tick(int time);
+ void createParticle(int time);
+ void updateOpacity(QFxParticle &p, int age);
+
+ QString source;
+ QUrl url;
+ QSimpleCanvasConfig::Image image;
+ int count;
+ int lifeSpan;
+ int lifeSpanDev;
+ int fadeInDur;
+ int fadeOutDur;
+ qreal angle;
+ qreal angleDev;
+ qreal velocity;
+ qreal velocityDev;
+ int addParticleTime;
+ int addParticleCount;
+ int lastAdvTime;
+ bool stream;
+ int streamDelay;
+ bool emitting;
+ QFxParticleMotion *motion;
+
+ QList<QFxParticle> particles;
+ QTickAnimationProxy<QFxParticlesPrivate, &QFxParticlesPrivate::tick> clock;
+
+#if defined(QFX_RENDER_OPENGL)
+ bool texDirty;
+ GLTexture tex;
+#endif
+};
+
+//TODO: Stop the clock if no visible particles and not emitting (restart on emittingChanged)
+void QFxParticlesPrivate::tick(int time)
+{
+ Q_Q(QFxParticles);
+ if (!motion)
+ motion = new QFxParticleMotionLinear(q);
+
+ int oldCount = particles.count();
+ int removed = 0;
+ int interval = time - lastAdvTime;
+ for (int i = 0; i < particles.count(); ) {
+ QFxParticle &particle = particles[i];
+ int age = time - particle.birthTime;
+ if (age >= particle.lifeSpan) {
+ QFxParticle part = particles.takeAt(i);
+ motion->destroy(part);
+ ++removed;
+ } else {
+ updateOpacity(particle, age);
+ motion->advance(particle, interval);
+ ++i;
+ }
+ }
+
+ while(removed-- && particles.count() < count && emitting)
+ createParticle(time);
+
+ if (!addParticleTime)
+ addParticleTime = time;
+
+ if (particles.count() < count && emitting) {
+ qreal perc = (lifeSpanDev <= 0)?(1.):(qreal(time - addParticleTime) / qreal(lifeSpanDev));
+ int percCount = addParticleCount + (int)perc * (count - addParticleCount);
+ int streamWidth = -1;
+ if (stream){
+ if (streamDelay > time){
+ streamWidth = 0;
+ }else{
+ int missed = time - streamDelay;
+ qreal streamWidthReal = qreal(count)/qreal(lifeSpan);
+ if (streamWidthReal < 1){
+ streamDelay = time + (int)(1.0/streamWidthReal);
+ streamWidth = 1;
+ streamWidth += missed/streamDelay;
+ }else{
+ streamWidth = qRound(streamWidthReal * (time-lastAdvTime));
+ }
+ }
+ }
+ while(particles.count() < count && particles.count() < percCount && streamWidth--)
+ createParticle(time);
+ }
+
+ lastAdvTime = time;
+ if (oldCount || particles.count()) {
+ if (q->itemParent())
+ q->itemParent()->update();
+ else
+ q->update();
+ } else if (!count) {
+ lastAdvTime = 0;
+ clock.stop();
+ }
+}
+
+void QFxParticlesPrivate::createParticle(int time)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::CreateParticle> x;
+#endif
+ Q_Q(QFxParticles);
+ QFxParticle p(time);
+ p.x = q->x() + q->width() * qreal(rand()) / RAND_MAX - image.width()/2.0;
+ p.y = q->y() + q->height() * qreal(rand()) / RAND_MAX - image.height()/2.0;
+ p.lifeSpan = lifeSpan;
+ if (lifeSpanDev)
+ p.lifeSpan += int(lifeSpanDev/2 - lifeSpanDev * qreal(rand()) / RAND_MAX);
+ p.fadeOutAge = p.lifeSpan - fadeOutDur;
+ if (fadeInDur == 0.) {
+ p.state= QFxParticle::Solid;
+ p.opacity = 1.0;
+ }
+ qreal a = angle;
+ if (angleDev)
+ a += angleDev/2 - angleDev * qreal(rand()) / RAND_MAX;
+ if (a > M_PI)
+ a = a - 2 * M_PI;
+ qreal v = velocity;
+ if (velocityDev)
+ v += velocityDev/2 - velocityDev * qreal(rand()) / RAND_MAX;
+ p.x_velocity = v * fastCos(a);
+ p.y_velocity = v * fastSin(a);
+ particles.append(p);
+ motion->created(particles.last());
+}
+
+void QFxParticlesPrivate::updateOpacity(QFxParticle &p, int age)
+{
+ switch (p.state) {
+ case QFxParticle::FadeIn:
+ if (age <= fadeInDur) {
+ p.opacity = qreal(age) / fadeInDur;
+ break;
+ } else {
+ p.opacity = 1.0;
+ p.state = QFxParticle::Solid;
+ // Fall through
+ }
+ case QFxParticle::Solid:
+ if (age <= p.fadeOutAge) {
+ break;
+ } else {
+ p.state = QFxParticle::FadeOut;
+ // Fall through
+ }
+ case QFxParticle::FadeOut:
+ p.opacity = qreal(p.lifeSpan - age) / fadeOutDur;
+ break;
+ }
+}
+
+QML_DEFINE_TYPE(QFxParticles,Particles);
+
+/*!
+ \qmlclass Particles
+ \brief The Particles object generates and moves particles.
+ \inherits Item
+
+ The particles created by this object cannot be dealt with directly, they can only be controlled through the parameters of the Particles object. The particles are all the same pixmap, specified by the user.
+
+ The particles are painted relative to the parent of the Particles object. Moving the
+ Particles object will not move the particles already emitted.
+
+ The below example creates two differently behaving particle sources.
+ The top one has particles falling from the top like snow,
+ the lower one has particles expelled up like a fountain.
+
+ \qml
+Rect {
+ width: 240
+ height: 320
+ color: "black"
+ Particles {
+ y: 0
+ width: parent.width
+ height: 30
+ source: "star.png"
+ lifeSpan: 5000
+ count: 50
+ angle: 70
+ angleDeviation: 36
+ velocity: 30
+ velocityDeviation: 10
+ ParticleMotionWander {
+ xvariance: 30
+ pace: 100
+ }
+ }
+ Particles {
+ y: 300
+ x: 120
+ width: 1
+ height: 1
+ source: "star.png"
+ lifeSpan: 5000
+ count: 200
+ angle: 270
+ angleDeviation: 45
+ velocity: 50
+ velocityDeviation: 30
+ ParticleMotionGravity {
+ yattractor: 1000
+ xattractor: 0
+ acceleration: 25
+ }
+ }
+}
+ \endqml
+ \image particles.gif
+*/
+
+/*!
+ \internal
+ \class QFxParticles
+ \ingroup group_effects
+ \brief The QFxParticles class generates and moves particles.
+*/
+
+QFxParticles::QFxParticles(QFxItem *parent)
+ : QFxItem(*(new QFxParticlesPrivate), parent)
+{
+ Q_D(QFxParticles);
+ d->init();
+ setOptions(HasContents);
+}
+
+QFxParticles::QFxParticles(QFxParticlesPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxParticles);
+ d->init();
+ setOptions(HasContents);
+}
+
+QFxParticles::~QFxParticles()
+{
+}
+
+/*!
+ \qmlproperty string Particles::src
+ This property holds the URL of the particle image.
+*/
+
+/*!
+ \property QFxParticles::source
+ \brief the URL of the particle image.
+*/
+QString QFxParticles::source() const
+{
+ Q_D(const QFxParticles);
+ return d->source;
+}
+
+void QFxParticles::imageLoaded()
+{
+ Q_D(QFxParticles);
+ d->image = QFxPixmap(d->url);
+#if defined(QFX_RENDER_OPENGL)
+ d->texDirty = true;
+ d->tex.clear();
+#endif
+ update();
+}
+
+void QFxParticles::setSource(const QString &name)
+{
+ Q_D(QFxParticles);
+
+ if (name == d->source)
+ return;
+
+ if (!d->source.isEmpty())
+ QFxPixmap::cancelGet(d->url, this);
+ if (name.isEmpty()) {
+ d->source = name;
+ d->url = QUrl();
+ d->image = QSimpleCanvasConfig::Image();
+#if defined(QFX_RENDER_OPENGL)
+ d->texDirty = true;
+ d->tex.clear();
+#endif
+ update();
+ } else {
+ d->source = name;
+ d->url = qmlContext(this)->resolvedUrl(name);
+ QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(imageLoaded()));
+ }
+}
+
+/*!
+ \qmlproperty int Particles::count
+ This property holds the target number of particles
+*/
+
+/*!
+ \property QFxParticles::count
+ \brief the target number of particles
+*/
+int QFxParticles::count() const
+{
+ Q_D(const QFxParticles);
+ return d->count;
+}
+
+void QFxParticles::setCount(int cnt)
+{
+ Q_D(QFxParticles);
+ if (cnt != d->count) {
+ if (!d->count && d->clock.state() != QAbstractAnimation::Running)
+ d->clock.start(); // infinity??
+ d->count = cnt;
+ d->addParticleTime = 0;
+ d->addParticleCount = d->particles.count();
+ update();
+ }
+}
+
+/*!
+ \qmlproperty int Particles::lifeSpan
+ \qmlproperty int Particles::lifeSpanDeviation
+
+ These properties describe the life span of each particle.
+
+ The default lifespan for a particle is 1000ms.
+
+ lifeSpanDeviation randomly varies the lifeSpan up to the specified variation. For
+ example, the following creates particles whose lifeSpan will vary
+ from 150ms to 250ms:
+
+ \qml
+Particles {
+ source: "star.png"
+ lifeSpan: 200
+ lifeSpanDeviation: 100
+}
+ \endqml
+*/
+
+/*!
+ \property QFxParticles::lifeSpan
+ \brief the life span of each particle.
+
+ Default value is 1000ms.
+
+ \sa QFxParticles::lifeSpanDeviation
+*/
+int QFxParticles::lifeSpan() const
+{
+ Q_D(const QFxParticles);
+ return d->lifeSpan;
+}
+
+void QFxParticles::setLifeSpan(int ls)
+{
+ Q_D(QFxParticles);
+ d->lifeSpan = ls;
+}
+
+/*!
+ \property QFxParticles::lifeSpanDeviation
+ \brief the maximum possible deviation from the set lifeSpan.
+
+ Randomly varies the lifeSpan up to the specified variation. For
+ example, the following creates particles whose lifeSpan will vary
+ from 150ms to 250ms:
+
+\qml
+Particles {
+ source: "star.png"
+ lifeSpan: 200
+ lifeSpanDeviation: 100
+}
+\endqml
+
+ \sa QFxParticles::lifeSpan
+*/
+int QFxParticles::lifeSpanDeviation() const
+{
+ Q_D(const QFxParticles);
+ return d->lifeSpanDev;
+}
+
+void QFxParticles::setLifeSpanDeviation(int dev)
+{
+ Q_D(QFxParticles);
+ d->lifeSpanDev = dev;
+}
+
+/*!
+ \qmlproperty int Particles::fadeInDuration
+ \qmlproperty int Particles::fadeOutDuration
+ These properties hold the time taken to fade the particles in and out.
+
+ By default fade in is 200ms and fade out is 300ms.
+*/
+
+/*!
+ \property QFxParticles::fadeInDuration
+ \brief the time taken to fade in the particles.
+
+ Default value is 200ms.
+*/
+int QFxParticles::fadeInDuration() const
+{
+ Q_D(const QFxParticles);
+ return d->fadeInDur;
+}
+
+void QFxParticles::setFadeInDuration(int dur)
+{
+ Q_D(QFxParticles);
+ if (dur >= 0.0)
+ d->fadeInDur = dur;
+}
+
+/*!
+ \property QFxParticles::fadeOutDuration
+ \brief the time taken to fade out the particles.
+
+ Default value is 300ms.
+*/
+int QFxParticles::fadeOutDuration() const
+{
+ Q_D(const QFxParticles);
+ return d->fadeOutDur;
+}
+
+void QFxParticles::setFadeOutDuration(int dur)
+{
+ Q_D(QFxParticles);
+ if (dur >= 0.0)
+ d->fadeOutDur = dur;
+}
+
+/*!
+ \qmlproperty real Particles::angle
+ \qmlproperty real Particles::angleDeviation
+
+ These properties control particle direction.
+
+ angleDeviation randomly varies the direction up to the specified variation. For
+ example, the following creates particles whose initial direction will
+ vary from 15 degrees to 105 degrees:
+
+ \qml
+Particles {
+ source: "star.png"
+ angle: 60
+ angleDeviation: 90
+}
+ \endqml
+*/
+
+/*!
+ \property QFxParticles::angle
+ \brief the initial angle of direction.
+
+ \sa QFxParticles::angleDeviation
+*/
+qreal QFxParticles::angle() const
+{
+ Q_D(const QFxParticles);
+ return d->angle * 180.0 / M_PI;
+}
+
+void QFxParticles::setAngle(qreal angle)
+{
+ Q_D(QFxParticles);
+ d->angle = angle * M_PI / 180.0;
+}
+
+/*!
+ \property QFxParticles::angleDeviation
+ \brief the maximum possible deviation from the set angle.
+
+ Randomly varies the direction up to the specified variation. For
+ example, the following creates particles whose initial direction will
+ vary from 15 degrees to 105 degrees:
+
+\qml
+Particles {
+ source: "star.png"
+ angle: 60
+ angleDeviation: 90
+}
+\endqml
+
+ \sa QFxParticles::angle
+*/
+qreal QFxParticles::angleDeviation() const
+{
+ Q_D(const QFxParticles);
+ return d->angleDev * 180.0 / M_PI;
+}
+
+void QFxParticles::setAngleDeviation(qreal dev)
+{
+ Q_D(QFxParticles);
+ d->angleDev = dev * M_PI / 180.0;;
+}
+
+/*!
+ \qmlproperty real Particles::velocity
+ \qmlproperty real Particles::velocityDeviation
+
+ These properties control the velocity of the particles.
+
+ velocityDeviation randomly varies the velocity up to the specified variation. For
+ example, the following creates particles whose initial velocity will
+ vary from 40 to 60.
+
+ \qml
+Particles {
+ source: "star.png"
+ velocity: 50
+ velocityDeviation: 20
+}
+ \endqml
+*/
+
+/*!
+ \property QFxParticles::velocity
+ \brief the initial velocity of the particles.
+
+ \sa QFxParticles::velocityDeviation
+*/
+qreal QFxParticles::velocity() const
+{
+ Q_D(const QFxParticles);
+ return d->velocity * 1000.0;
+}
+
+void QFxParticles::setVelocity(qreal velocity)
+{
+ Q_D(QFxParticles);
+ d->velocity = velocity / 1000.0;
+}
+
+/*!
+ \property QFxParticles::velocityDeviation
+ \brief the maximum possible deviation from the set velocity.
+
+ Randomly varies the velocity up to the specified variation. For
+ example, the following creates particles whose initial velocity will
+ vary from 40 to 60.
+
+\qml
+Particles {
+ source: "star.png"
+ velocity: 50
+ velocityDeviation: 20
+}
+\endqml
+
+ \sa QFxParticles::velocity
+*/
+qreal QFxParticles::velocityDeviation() const
+{
+ Q_D(const QFxParticles);
+ return d->velocityDev * 1000.0;
+}
+
+void QFxParticles::setVelocityDeviation(qreal velocity)
+{
+ Q_D(QFxParticles);
+ d->velocityDev = velocity / 1000.0;
+}
+
+/*!
+ \qmlproperty bool Particles::streamIn
+ This property determines whether the particles stream in at a constant rate
+
+ When stream is set to true the particles will stream in at a constant rate.
+ Otherwise the particles will appear as a clump. Note that this only affects the
+ start of the particle effect, variables such as lifespan deviation can cause the
+ particles to unclump over time.
+*/
+/*!
+ \property QFxParticles::streamIn
+ \brief determines whether the particles stream in at a constant rate
+
+ When stream is set to true the particles will stream in at a constant rate.
+ Otherwise the particles will appear as a clump. Note that this only affects the
+ start of the particle effect, variables such as lifespan deviation can cause the
+
+*/
+//The name may need a rethink
+bool QFxParticles::streamIn() const
+{
+ Q_D(const QFxParticles);
+ return d->stream;
+}
+
+void QFxParticles::setStreamIn(bool b)
+{
+ Q_D(QFxParticles);
+ d->stream = b;
+}
+
+/*!
+ \qmlproperty bool Particles::emitting
+ This property determines whether new particles are created
+
+ If emitting is set to false no new particles will be created. This means that
+ when a particle reaches the end of its lifespan it is not replaced. This
+ property can be used to turn particles on and off with a more natural look.
+
+ The default setting is true. Note that if it initialized to false no particles
+ will be produced until it is set to true.
+*/
+/*!
+ \property QFxParticles::emitting
+ If emitting is set to false no new particles will be created. This means that
+ when a particle reaches the end of its lifespan it is not replaced. This
+ property can be used to turn particles on and off with a more natural look.
+
+ The default setting is true. Note that if it initialized to false no particles
+ will be produced until it is set to true.
+*/
+bool QFxParticles::emitting() const
+{
+ Q_D(const QFxParticles);
+ return d->emitting;
+}
+
+void QFxParticles::setEmitting(bool r)
+{
+ Q_D(QFxParticles);
+ d->emitting = r;
+}
+/*!
+ \qmlproperty ParticleMotion Particles::motion
+ This property sets the type of motion to apply to the particles.
+
+ When a particle is created it will have an initial direction and velocity.
+ The motion of the particle during its lifeSpan is then influenced by the
+ motion property.
+
+ Default motion is ParticleMotionLinear.
+*/
+
+/*!
+ \property QFxParticles::motion
+ \brief sets the type of motion to apply to the particles.
+
+ When a particle is created it will have an initial direction and velocity.
+ The motion of the particle during its lifeSpan is then influenced by the
+ motion property.
+
+ Default motion is QFxParticleMotionLinear.
+*/
+QFxParticleMotion *QFxParticles::motion() const
+{
+ Q_D(const QFxParticles);
+ return d->motion;
+}
+
+void QFxParticles::setMotion(QFxParticleMotion *motion)
+{
+ Q_D(QFxParticles);
+ d->motion = motion;
+}
+
+void QFxParticles::dump(int depth)
+{
+ Q_D(QFxParticles);
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << "URL:" << d->url << "Count:" << d->count;
+ QFxItem::dump(depth);
+}
+
+QString QFxParticles::propertyInfo() const
+{
+ Q_D(const QFxParticles);
+ return d->url.toString();
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+void QFxParticles::paintContents(QPainter &p)
+{
+ Q_D(QFxParticles);
+ if (d->image.isNull())
+ return;
+
+ const int myX = x();
+ const int myY = y();
+ for (int i = 0; i < d->particles.count(); ++i) {
+ const QFxParticle &particle = d->particles.at(i);
+ p.setOpacity(particle.opacity);
+ p.drawImage(particle.x-myX, particle.y-myY, d->image);
+ }
+}
+#elif defined(QFX_RENDER_OPENGL2)
+void QFxParticles::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxParticles);
+ if (d->image.isNull())
+ return;
+
+ if (d->texDirty && !d->image.isNull()) {
+ d->tex.setImage(d->image);
+ d->tex.setHorizontalWrap(GLTexture::Repeat);
+ d->tex.setVerticalWrap(GLTexture::Repeat);
+ }
+ d->texDirty = false;
+
+ SingleTextureOpacityShader *shader = basicShaders()->singleTextureOpacity();
+ shader->enable();
+ shader->setTransform(p.activeTransform);
+
+ glBindTexture(GL_TEXTURE_2D, d->tex.texture());
+
+ const int myX = (int)x();
+ const int myY = (int)y();
+ float widthV = d->image.width();
+ float heightV = d->image.height();
+ for (int i = 0; i < d->particles.count(); ++i) {
+ const QFxParticle &particle = d->particles.at(i);
+ float left = particle.x - myX;
+ float right = particle.x - myX + widthV;
+ float top = particle.y - myY;
+ float bottom = particle.y - myY + heightV;
+
+ GLfloat vertices[] = { left, bottom,
+ right, bottom,
+ left, top,
+ right, top };
+
+ GLfloat texVertices[] = { 0, 0,
+ 1, 0,
+ 0, 1,
+ 1, 1 };
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2);
+ shader->setOpacity(particle.opacity * p.activeOpacity);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ }
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+}
+#endif
+
+void QFxParticles::componentComplete()
+{
+ Q_D(QFxParticles);
+ QFxItem::componentComplete();
+ if (d->count)
+ d->clock.start(); // infinity??
+ if (d->lifeSpanDev > d->lifeSpan)
+ d->lifeSpanDev = d->lifeSpan;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxparticles.h b/src/declarative/fx/qfxparticles.h
new file mode 100644
index 0000000..0696e60
--- /dev/null
+++ b/src/declarative/fx/qfxparticles.h
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXPARTICLES_H
+#define QFXPARTICLES_H
+
+#include <qfxitem.h>
+
+#if defined(QFX_RENDER_OPENGL)
+#include "gltexture.h"
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QFxParticle;
+class QFxParticles;
+class QFxParticleMotion : public QObject
+{
+ Q_OBJECT
+public:
+ QFxParticleMotion(QObject *parent=0);
+
+ virtual void advance(QFxParticle &, int interval);
+ virtual void created(QFxParticle &);
+ virtual void destroy(QFxParticle &);
+};
+QML_DECLARE_TYPE(QFxParticleMotion);
+
+class QFxParticleMotionLinear : public QFxParticleMotion
+{
+ Q_OBJECT
+public:
+ QFxParticleMotionLinear(QObject *parent=0)
+ : QFxParticleMotion(parent) {}
+
+ virtual void advance(QFxParticle &, int interval);
+};
+QML_DECLARE_TYPE(QFxParticleMotionLinear);
+
+class QFxParticleMotionGravity : public QFxParticleMotion
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int xattractor READ xAttractor WRITE setXAttractor)
+ Q_PROPERTY(int yattractor READ yAttractor WRITE setYAttractor)
+ Q_PROPERTY(int acceleration READ acceleration WRITE setAcceleration)
+public:
+ QFxParticleMotionGravity(QObject *parent=0)
+ : QFxParticleMotion(parent), _xAttr(0), _yAttr(0), _accel(0.00005) {}
+
+ int xAttractor() const { return _xAttr; }
+ void setXAttractor(int x) { _xAttr = x; }
+
+ int yAttractor() const { return _yAttr; }
+ void setYAttractor(int y) { _yAttr = y; }
+
+ int acceleration() const { return int(_accel * 1000000); }
+ void setAcceleration(int accel) { _accel = qreal(accel)/1000000.0; }
+
+ virtual void advance(QFxParticle &, int interval);
+
+private:
+ int _xAttr;
+ int _yAttr;
+ qreal _accel;
+};
+QML_DECLARE_TYPE(QFxParticleMotionGravity);
+
+class QFxParticleMotionWander : public QFxParticleMotion
+{
+ Q_OBJECT
+public:
+ QFxParticleMotionWander()
+ : QFxParticleMotion(), particles(0), _xvariance(0), _yvariance(0) {}
+
+ virtual void advance(QFxParticle &, int interval);
+ virtual void created(QFxParticle &);
+ virtual void destroy(QFxParticle &);
+
+ struct Data {
+ qreal x_targetV;
+ qreal y_targetV;
+ qreal x_peak;
+ qreal y_peak;
+ qreal x_var;
+ qreal y_var;
+ };
+
+ Q_PROPERTY(int xvariance READ xVariance WRITE setXVariance);
+ int xVariance() const { return int(_xvariance * 1000); }
+ void setXVariance(int var) { _xvariance = var / 1000.0; }
+
+ Q_PROPERTY(int yvariance READ yVariance WRITE setYVariance);
+ int yVariance() const { return int(_yvariance * 1000); }
+ void setYVariance(int var) { _yvariance = var / 1000.0; }
+
+ Q_PROPERTY(int pace READ pace WRITE setPace);
+ int pace() const { return int(_pace * 1000); }
+ void setPace(int pace) { _pace = pace / 1000.0; }
+
+private:
+ QFxParticles *particles;
+ qreal _xvariance;
+ qreal _yvariance;
+ qreal _pace;
+};
+QML_DECLARE_TYPE(QFxParticleMotionWander);
+
+class QFxParticlesPrivate;
+class Q_DECLARATIVE_EXPORT QFxParticles : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString source READ source WRITE setSource);
+ Q_PROPERTY(int count READ count WRITE setCount);
+ Q_PROPERTY(int lifeSpan READ lifeSpan WRITE setLifeSpan);
+ Q_PROPERTY(int lifeSpanDeviation READ lifeSpanDeviation WRITE setLifeSpanDeviation);
+ Q_PROPERTY(int fadeInDuration READ fadeInDuration WRITE setFadeInDuration);
+ Q_PROPERTY(int fadeOutDuration READ fadeOutDuration WRITE setFadeOutDuration);
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle);
+ Q_PROPERTY(qreal angleDeviation READ angleDeviation WRITE setAngleDeviation);
+ Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity);
+ Q_PROPERTY(qreal velocityDeviation READ velocityDeviation WRITE setVelocityDeviation);
+ Q_PROPERTY(bool streamIn READ streamIn WRITE setStreamIn);
+ Q_PROPERTY(bool emitting READ emitting WRITE setEmitting);
+ Q_PROPERTY(QFxParticleMotion *motion READ motion WRITE setMotion);
+ Q_CLASSINFO("DefaultProperty", "motion");
+
+public:
+ QFxParticles(QFxItem *parent=0);
+ ~QFxParticles();
+
+ QString source() const;
+ void setSource(const QString &);
+
+ int count() const;
+ void setCount(int cnt);
+
+ int lifeSpan() const;
+ void setLifeSpan(int);
+
+ int lifeSpanDeviation() const;
+ void setLifeSpanDeviation(int);
+
+ int fadeInDuration() const;
+ void setFadeInDuration(int);
+
+ int fadeOutDuration() const;
+ void setFadeOutDuration(int);
+
+ qreal angle() const;
+ void setAngle(qreal);
+
+ qreal angleDeviation() const;
+ void setAngleDeviation(qreal);
+
+ qreal velocity() const;
+ void setVelocity(qreal);
+
+ qreal velocityDeviation() const;
+ void setVelocityDeviation(qreal);
+
+ bool streamIn() const;
+ void setStreamIn(bool);
+
+ bool emitting() const;
+ void setEmitting(bool);
+
+ QFxParticleMotion *motion() const;
+ void setMotion(QFxParticleMotion *);
+
+ virtual void dump(int depth);
+ virtual QString propertyInfo() const;
+
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &p);
+#elif defined(QFX_RENDER_OPENGL2)
+ void paintGLContents(GLPainter &);
+#endif
+
+protected:
+ virtual void componentComplete();
+ QFxParticles(QFxParticlesPrivate &dd, QFxItem *parent);
+
+private Q_SLOTS:
+ void imageLoaded();
+
+private:
+ Q_DISABLE_COPY(QFxParticles)
+ Q_DECLARE_PRIVATE(QFxParticles)
+};
+QML_DECLARE_TYPE(QFxParticles);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/fx/qfxpath.cpp b/src/declarative/fx/qfxpath.cpp
new file mode 100644
index 0000000..e11658c
--- /dev/null
+++ b/src/declarative/fx/qfxpath.cpp
@@ -0,0 +1,865 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxpath.h"
+#include "qfxpath_p.h"
+#include <qfxperf.h>
+#include <private/qbezier_p.h>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxPath,Path);
+QML_DEFINE_NOCREATE_TYPE(QFxPathElement);
+QML_DEFINE_NOCREATE_TYPE(QFxCurve);
+QML_DEFINE_TYPE(QFxPathAttribute,PathAttribute);
+QML_DEFINE_TYPE(QFxPathPercent,PathPercent);
+QML_DEFINE_TYPE(QFxPathLine,PathLine);
+QML_DEFINE_TYPE(QFxPathQuad,PathQuad);
+QML_DEFINE_TYPE(QFxPathCubic,PathCubic);
+
+/*!
+ \qmlclass PathElement
+ \brief PathElement is the base path type.
+
+ This type is the base for all path types. It cannot
+ be instantiated.
+
+ \sa Path, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic
+*/
+
+/*!
+ \internal
+ \class QFxPathElement
+ \ingroup group_utility
+*/
+
+/*!
+ \qmlclass Path QFxPath
+ \brief A Path object defines a path for use by \l PathView.
+
+ A Path is composed of one or more path segments - PathLine, PathQuad,
+ PathCubic.
+
+ The spacing of the items along the Path can be adjusted via a
+ PathPercent object.
+
+ PathAttribute allows named attributes with values to be defined
+ along the path.
+
+ \sa PathView, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic
+*/
+
+/*!
+ \internal
+ \class QFxPath
+ \ingroup group_utility
+ \brief The QFxPath class defines a path.
+ \sa QFxPathView
+*/
+QFxPath::QFxPath(QObject *parent)
+ : QObject(*(new QFxPathPrivate), parent)
+{
+}
+
+QFxPath::QFxPath(QFxPathPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+QFxPath::~QFxPath()
+{
+}
+
+/*!
+ \qmlproperty real Path::startX
+ \qmlproperty real Path::startY
+ This property holds the starting position of the path.
+*/
+
+/*!
+ \property QFxPath::startX
+ \brief the starting x position of the path.
+*/
+
+qreal QFxPath::startX() const
+{
+ Q_D(const QFxPath);
+ return d->startX;
+}
+
+void QFxPath::setStartX(qreal x)
+{
+ Q_D(QFxPath);
+ d->startX = x;
+}
+
+
+/*!
+ \property QFxPath::startY
+ \brief the starting y position of the path.
+*/
+
+qreal QFxPath::startY() const
+{
+ Q_D(const QFxPath);
+ return d->startY;
+}
+
+void QFxPath::setStartY(qreal y)
+{
+ Q_D(QFxPath);
+ d->startY = y;
+}
+
+/*!
+ \qmlproperty list<PathElement> Path::pathElements
+ This property holds the objects composing the path.
+
+ \default
+
+ A path can contain the following path objects:
+ \list
+ \i \l PathLine - a straight line to a given position.
+ \i \l PathQuad - a quadratic Bezier curve to a given position with a control point.
+ \i \l PathCubic - a cubic Bezier curve to a given position with two control points.
+ \i \l PathAttribute - an attribute at a given position in the path.
+ \i \l PathPercent - a way to spread out items along various segments of the path.
+ \endlist
+
+ \snippet doc/src/snippets/declarative/pathview/pathattributes.qml 2
+*/
+
+QList<QFxPathElement *>* QFxPath::pathElements()
+{
+ Q_D(QFxPath);
+ return &(d->_pathElements);
+}
+
+void QFxPath::interpolate(int idx, const QString &name, qreal value)
+{
+ Q_D(QFxPath);
+ if (!idx)
+ return;
+
+ qreal lastValue = 0;
+ qreal lastPercent = 0;
+ int search = idx - 1;
+ while(search >= 0) {
+ const AttributePoint &point = d->_attributePoints.at(search);
+ if (point.values.contains(name)) {
+ lastValue = point.values.value(name);
+ lastPercent = point.origpercent;
+ break;
+ }
+ --search;
+ }
+
+ ++search;
+
+ const AttributePoint &curPoint = d->_attributePoints.at(idx);
+
+ for (int ii = search; ii < idx; ++ii) {
+ AttributePoint &point = d->_attributePoints[ii];
+
+ qreal val = lastValue + (value - lastValue) * (point.origpercent - lastPercent) / (curPoint.origpercent - lastPercent);
+ point.values.insert(name, val);
+ }
+}
+
+void QFxPath::endpoint(const QString &name)
+{
+ Q_D(QFxPath);
+ const AttributePoint &first = d->_attributePoints.first();
+ qreal val = first.values.value(name);
+ for (int ii = d->_attributePoints.count() - 1; ii >= 0; ii--) {
+ const AttributePoint &point = d->_attributePoints.at(ii);
+ if (point.values.contains(name)) {
+ for (int jj = ii + 1; jj < d->_attributePoints.count(); ++jj) {
+ AttributePoint &setPoint = d->_attributePoints[jj];
+ setPoint.values.insert(name, val);
+ }
+ return;
+ }
+ }
+}
+
+void QFxPath::processPath()
+{
+ Q_D(QFxPath);
+
+ d->_pointCache.clear();
+ d->_attributePoints.clear();
+ d->_path = QPainterPath();
+
+ AttributePoint first;
+ for (int ii = 0; ii < d->_attributes.count(); ++ii)
+ first.values[d->_attributes.at(ii)] = 0;
+ d->_attributePoints << first;
+
+ d->_path.moveTo(d->startX, d->startY);
+
+ foreach (QFxPathElement *pathElement, d->_pathElements) {
+ if (QFxCurve *curve = qobject_cast<QFxCurve *>(pathElement)) {
+ curve->addToPath(d->_path);
+ AttributePoint p;
+ p.origpercent = d->_path.length();
+ d->_attributePoints << p;
+ } else if (QFxPathAttribute *attribute = qobject_cast<QFxPathAttribute *>(pathElement)) {
+ AttributePoint &point = d->_attributePoints.last();
+ point.values[attribute->name()] = attribute->value();
+ interpolate(d->_attributePoints.count() - 1, attribute->name(), attribute->value());
+ } else if (QFxPathPercent *percent = qobject_cast<QFxPathPercent *>(pathElement)) {
+ AttributePoint &point = d->_attributePoints.last();
+ point.values[QLatin1String("_qfx_percent")] = percent->value();
+ interpolate(d->_attributePoints.count() - 1, QLatin1String("_qfx_percent"), percent->value());
+ }
+ }
+
+ // Fixup end points
+ const AttributePoint &last = d->_attributePoints.last();
+ for (int ii = 0; ii < d->_attributes.count(); ++ii) {
+ if (!last.values.contains(d->_attributes.at(ii)))
+ endpoint(d->_attributes.at(ii));
+ }
+
+ // Adjust percent
+ qreal length = d->_path.length();
+ qreal prevpercent = 0;
+ qreal prevorigpercent = 0;
+ for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ const AttributePoint &point = d->_attributePoints.at(ii);
+ if (point.values.contains(QLatin1String("_qfx_percent"))) { //special string for QFxPathPercent
+ if ( ii > 0) {
+ qreal scale = (d->_attributePoints[ii].origpercent/length - prevorigpercent) /
+ (point.values.value(QLatin1String("_qfx_percent"))-prevpercent);
+ d->_attributePoints[ii].scale = scale;
+ }
+ d->_attributePoints[ii].origpercent /= length;
+ d->_attributePoints[ii].percent = point.values.value(QLatin1String("_qfx_percent"));
+ prevorigpercent = d->_attributePoints[ii].origpercent;
+ prevpercent = d->_attributePoints[ii].percent;
+ } else {
+ d->_attributePoints[ii].origpercent /= length;
+ d->_attributePoints[ii].percent = d->_attributePoints[ii].origpercent;
+ }
+ }
+
+ emit changed();
+}
+
+void QFxPath::componentComplete()
+{
+ Q_D(QFxPath);
+ QSet<QString> attrs;
+ // First gather up all the attributes
+ foreach (QFxPathElement *pathElement, d->_pathElements) {
+ if (QFxPathAttribute *attribute =
+ qobject_cast<QFxPathAttribute *>(pathElement))
+ attrs.insert(attribute->name());
+ }
+ d->_attributes = attrs.toList();
+
+ processPath();
+
+ foreach (QFxPathElement *pathElement, d->_pathElements)
+ connect(pathElement, SIGNAL(changed()), this, SLOT(processPath()));
+}
+
+QPainterPath QFxPath::path() const
+{
+ Q_D(const QFxPath);
+ return d->_path;
+}
+
+QStringList QFxPath::attributes() const
+{
+ Q_D(const QFxPath);
+ return d->_attributes;
+}
+#include <QTime>
+
+static inline QBezier nextBezier(const QPainterPath &path, int *from, qreal *bezLength)
+{
+ const int lastElement = path.elementCount() - 1;
+ for (int i=*from; i <= lastElement; ++i) {
+ const QPainterPath::Element &e = path.elementAt(i);
+
+ switch (e.type) {
+ case QPainterPath::MoveToElement:
+ break;
+ case QPainterPath::LineToElement:
+ {
+ QLineF line(path.elementAt(i-1), e);
+ *bezLength = line.length();
+ QPointF a = path.elementAt(i-1);
+ QPointF delta = e - a;
+ *from = i+1;
+ return QBezier::fromPoints(a, a + delta / 3, a + 2 * delta / 3, e);
+ }
+ case QPainterPath::CurveToElement:
+ {
+ QBezier b = QBezier::fromPoints(path.elementAt(i-1),
+ e,
+ path.elementAt(i+1),
+ path.elementAt(i+2));
+ *bezLength = b.length();
+ *from = i+3;
+ return b;
+ }
+ default:
+ break;
+ }
+ }
+ *from = lastElement;
+ *bezLength = 0;
+ return QBezier();
+}
+
+void QFxPath::createPointCache() const
+{
+ Q_D(const QFxPath);
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::PathCache> pc;
+#endif
+ qreal pathLength = d->_path.length();
+ const int points = int(pathLength*2);
+ const int lastElement = d->_path.elementCount() - 1;
+ d->_pointCache.resize(points+1);
+
+ int currElement = 0;
+ qreal bezLength = 0;
+ QBezier currBez = nextBezier(d->_path, &currElement, &bezLength);
+ qreal currLength = bezLength;
+ qreal epc = currLength / pathLength;
+
+ for (int i = 0; i < d->_pointCache.size(); i++) {
+ //find which set we are in
+ qreal prevPercent = 0;
+ qreal prevOrigPercent = 0;
+ for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ qreal percent = qreal(i)/points;
+ const AttributePoint &point = d->_attributePoints.at(ii);
+ if (percent < point.percent || ii == d->_attributePoints.count() - 1) { //### || is special case for very last item
+ qreal elementPercent = (percent - prevPercent);
+
+ qreal spc = prevOrigPercent + elementPercent * point.scale;
+
+ while (spc > epc) {
+ if (currElement > lastElement)
+ break;
+ currBez = nextBezier(d->_path, &currElement, &bezLength);
+ if (bezLength == 0.0) {
+ currLength = pathLength;
+ epc = 1.0;
+ break;
+ }
+ currLength += bezLength;
+ epc = currLength / pathLength;
+ }
+ qreal realT = (pathLength * spc - (currLength - bezLength)) / bezLength;
+ d->_pointCache[i] = currBez.pointAt(qBound(qreal(0), realT, qreal(1)));
+ break;
+ }
+ prevOrigPercent = point.origpercent;
+ prevPercent = point.percent;
+ }
+ }
+}
+
+QPointF QFxPath::pointAt(qreal p) const
+{
+ Q_D(const QFxPath);
+ if (d->_pointCache.isEmpty()) {
+ createPointCache();
+ }
+ int idx = qRound(p*d->_pointCache.size());
+ if (idx >= d->_pointCache.size())
+ idx = d->_pointCache.size() - 1;
+ else if (idx < 0)
+ idx = 0;
+ return d->_pointCache.at(idx);
+}
+
+qreal QFxPath::attributeAt(const QString &name, qreal percent) const
+{
+ Q_D(const QFxPath);
+ if (percent < 0 || percent > 1)
+ return 0;
+
+ for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ const AttributePoint &point = d->_attributePoints.at(ii);
+
+ if (point.percent == percent) {
+ return point.values.value(name);
+ } else if (point.percent > percent) {
+ qreal lastValue =
+ ii?(d->_attributePoints.at(ii - 1).values.value(name)):0;
+ qreal lastPercent =
+ ii?(d->_attributePoints.at(ii - 1).percent):0;
+ qreal curValue = point.values.value(name);
+ qreal curPercent = point.percent;
+
+ return lastValue + (curValue - lastValue) * (percent - lastPercent) / (curPercent - lastPercent);
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+
+qreal QFxCurve::x() const
+{
+ return _x;
+}
+
+void QFxCurve::setX(qreal x)
+{
+ if (_x != x) {
+ _x = x;
+ emit changed();
+ }
+}
+
+qreal QFxCurve::y() const
+{
+ return _y;
+}
+
+void QFxCurve::setY(qreal y)
+{
+ if (_y != y) {
+ _y = y;
+ emit changed();
+ }
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathAttribute
+ \brief The PathAttribute allows setting an attribute at a given position in a Path.
+
+ The PathAttribute object allows attibutes consisting of a name and a
+ value to be specified for the endpoints of path segments. The attributes
+ are exposed to the delegate as \l {Attached Properties}. The value of
+ an attribute at any particular point is interpolated from the PathAttributes
+ bounding the point.
+
+ The example below shows a path with the items scaled to 30% with opacity 50%
+ at the top of the path and scaled 100% with opacity 100% at the bottom.
+ Note the use of the PathView.scale and PathView.opacity attached properties
+ to set the scale and opacity of the delegate.
+ \table
+ \row
+ \o \image declarative-pathattribute.png
+ \o
+ \snippet doc/src/snippets/declarative/pathview/pathattributes.qml 0
+ \endtable
+
+ \sa Path
+*/
+
+/*!
+ \internal
+ \class QFxPathAttribute
+ \ingroup group_utility
+ \brief The QFxPathAttribute class allows to set the value of an attribute at a given position in the path.
+
+ \sa QFxPath
+*/
+
+
+/*!
+ \qmlproperty string PathAttribute::name
+ the name of the attribute to change.
+*/
+
+/*!
+ the name of the attribute to change.
+*/
+
+QString QFxPathAttribute::name() const
+{
+ return _name;
+}
+
+void QFxPathAttribute::setName(const QString &name)
+{
+ _name = name;
+}
+
+/*!
+ \qmlproperty string PathAttribute::value
+ the new value of the attribute.
+*/
+
+/*!
+ the new value of the attribute.
+*/
+qreal QFxPathAttribute::value() const
+{
+ return _value;
+}
+
+void QFxPathAttribute::setValue(qreal value)
+{
+ if (_value != value) {
+ _value = value;
+ emit changed();
+ }
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathLine
+ \brief The PathLine defines a straight line.
+
+ The example below creates a path consisting of a straight line from
+ 0,100 to 200,100:
+
+ \qml
+ Path {
+ startX: 0; startY: 100
+ PathLine { x: 200; y: 100 }
+ }
+ \endqml
+
+ \sa Path, PathQuad, PathCubic
+*/
+
+/*!
+ \internal
+ \class QFxPathLine
+ \ingroup group_utility
+ \brief The QFxPathLine class defines a straight line.
+
+ \sa QFxPath
+*/
+
+/*!
+ \qmlproperty real PathLine::x
+ \qmlproperty real PathLine::y
+
+ Defines the end point of the line.
+*/
+
+void QFxPathLine::addToPath(QPainterPath &path)
+{
+ path.lineTo(x(), y());
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathQuad
+ \brief The PathQuad defines a quadratic Bezier curve with a control point.
+
+ The following QML produces the path shown below:
+ \table
+ \row
+ \o \image declarative-pathquad.png
+ \o
+ \qml
+ Path {
+ startX: 0; startY: 0
+ PathQuad x: 200; y: 0; controlX: 100; controlY: 150 }
+ }
+ \endqml
+ \endtable
+
+ \sa Path, PathCubic, PathLine
+*/
+
+/*!
+ \internal
+ \class QFxPathQuad
+ \ingroup group_utility
+ \brief The QFxPathQuad class defines a quadratic Bezier curve with a control point.
+
+ \sa QFxPath
+*/
+
+
+/*!
+ \qmlproperty real PathQuad::x
+ \qmlproperty real PathQuad::y
+
+ Defines the end point of the curve.
+*/
+
+/*!
+ \qmlproperty real PathQuad::controlX
+ \qmlproperty real PathQuad::controlY
+
+ Defines the position of the control point.
+*/
+
+/*!
+ the x position of the control point.
+*/
+qreal QFxPathQuad::controlX() const
+{
+ return _controlX;
+}
+
+void QFxPathQuad::setControlX(qreal x)
+{
+ if (_controlX != x) {
+ _controlX = x;
+ emit changed();
+ }
+}
+
+
+/*!
+ the y position of the control point.
+*/
+qreal QFxPathQuad::controlY() const
+{
+ return _controlY;
+}
+
+void QFxPathQuad::setControlY(qreal y)
+{
+ if (_controlY != y) {
+ _controlY = y;
+ emit changed();
+ }
+}
+
+void QFxPathQuad::addToPath(QPainterPath &path)
+{
+ path.quadTo(controlX(), controlY(), x(), y());
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathCubic
+ \brief The PathCubic defines a cubic Bezier curve with two control points.
+
+ The following QML produces the path shown below:
+ \table
+ \row
+ \o \image declarative-pathcubic.png
+ \o
+ \qml
+ Path {
+ startX: 20; startY: 0
+ PathCubic {
+ x: 180; y: 0; control1X: -10; control1Y: 90
+ control2X: 210; control2Y: 90
+ }
+ }
+ \endqml
+ \endtable
+
+ \sa Path, PathQuad, PathLine
+*/
+
+/*!
+ \internal
+ \class QFxPathCubic
+ \ingroup group_utility
+ \brief The QFxPathCubic class defines a cubic Bezier curve with two control points.
+
+ \sa QFxPath
+*/
+
+/*!
+ \qmlproperty real PathCubic::x
+ \qmlproperty real PathCubic::y
+
+ Defines the end point of the curve.
+*/
+
+/*!
+ \qmlproperty real PathCubic::control1X
+ \qmlproperty real PathCubic::control1Y
+
+ Defines the position of the first control point.
+*/
+
+/*!
+ \property QFxPathCubic::control1X
+ \brief the x position of the first control point.
+*/
+qreal QFxPathCubic::control1X() const
+{
+ return _control1X;
+}
+
+void QFxPathCubic::setControl1X(qreal x)
+{
+ if (_control1X != x) {
+ _control1X = x;
+ emit changed();
+ }
+}
+
+/*!
+ \property QFxPathCubic::control1Y
+ \brief the y position of the first control point.
+*/
+qreal QFxPathCubic::control1Y() const
+{
+ return _control1Y;
+}
+
+void QFxPathCubic::setControl1Y(qreal y)
+{
+ if (_control1Y != y) {
+ _control1Y = y;
+ emit changed();
+ }
+}
+
+/*!
+ \qmlproperty real PathCubic::control2X
+ \qmlproperty real PathCubic::control2Y
+
+ Defines the position of the second control point.
+*/
+
+/*!
+ \property QFxPathCubic::control2X
+ \brief the x position of the second control point.
+*/
+qreal QFxPathCubic::control2X() const
+{
+ return _control2X;
+}
+
+void QFxPathCubic::setControl2X(qreal x)
+{
+ if (_control2X != x) {
+ _control2X = x;
+ emit changed();
+ }
+}
+
+/*!
+ \property QFxPathCubic::control2Y
+ \brief the y position of the second control point.
+*/
+qreal QFxPathCubic::control2Y() const
+{
+ return _control2Y;
+}
+
+void QFxPathCubic::setControl2Y(qreal y)
+{
+ if (_control2Y != y) {
+ _control2Y = y;
+ emit changed();
+ }
+}
+
+void QFxPathCubic::addToPath(QPainterPath &path)
+{
+ path.cubicTo(control1X(), control1Y(), control2X(), control2Y(), x(), y());
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathPercent
+ \brief The PathPercent manipulates the way a path is interpreted.
+
+ The examples below show the normal distrubution of items along a path
+ compared to a distribution which places 50% of the items along the
+ PathLine section of the path.
+ \table
+ \row
+ \o \image declarative-nopercent.png
+ \o
+ \qml
+ Path {
+ startX: 20; startY: 0
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathLine { x: 150; y: 80 }
+ PathQuad { x: 180; y: 0; controlX: 200; controlY: 80 }
+ }
+ \endqml
+ \row
+ \o \image declarative-percent.png
+ \o
+ \qml
+ Path {
+ startX: 20; startY: 0
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathPercent { value: 0.25 }
+ PathLine { x: 150; y: 80 }
+ PathPercent { value: 0.75 }
+ PathQuad { x: 180; y: 0; controlX: 200; controlY: 80 }
+ PathPercent { value: 1 }
+ }
+ \endqml
+ \endtable
+
+ \sa Path
+*/
+
+/*!
+ \internal
+ \class QFxPathPercent
+ \ingroup group_utility
+ \brief The QFxPathPercent class manipulates the way a path is interpreted.
+
+ QFxPathPercent allows you to bunch up items (or spread out items) along various
+ segments of a QFxPathView's path.
+
+ \sa QFxPath
+
+*/
+
+qreal QFxPathPercent::value() const
+{
+ return _value;
+}
+
+void QFxPathPercent::setValue(qreal value)
+{
+ _value = value;
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxpath.h b/src/declarative/fx/qfxpath.h
new file mode 100644
index 0000000..c594793
--- /dev/null
+++ b/src/declarative/fx/qfxpath.h
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXPATH_H
+#define QFXPATH_H
+
+#include <QObject>
+#include <QPainterPath>
+#include <qml.h>
+#include <qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QFxPathElement : public QObject
+{
+ Q_OBJECT
+public:
+ QFxPathElement(QObject *parent=0) : QObject(parent) {}
+Q_SIGNALS:
+ void changed();
+};
+QML_DECLARE_TYPE(QFxPathElement);
+
+class Q_DECLARATIVE_EXPORT QFxPathAttribute : public QFxPathElement
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY changed)
+public:
+ QFxPathAttribute(QObject *parent=0) : QFxPathElement(parent), _value(0) {}
+
+
+ QString name() const;
+ void setName(const QString &name);
+
+ qreal value() const;
+ void setValue(qreal value);
+
+private:
+ QString _name;
+ qreal _value;
+};
+QML_DECLARE_TYPE(QFxPathAttribute);
+
+class Q_DECLARATIVE_EXPORT QFxCurve : public QFxPathElement
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY changed)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY changed)
+public:
+ QFxCurve(QObject *parent=0) : QFxPathElement(parent), _x(0), _y(0) {}
+
+ qreal x() const;
+ void setX(qreal x);
+
+ qreal y() const;
+ void setY(qreal y);
+
+ virtual void addToPath(QPainterPath &) {}
+
+private:
+ qreal _x;
+ qreal _y;
+};
+QML_DECLARE_TYPE(QFxCurve);
+
+class Q_DECLARATIVE_EXPORT QFxPathLine : public QFxCurve
+{
+ Q_OBJECT
+public:
+ QFxPathLine(QObject *parent=0) : QFxCurve(parent) {}
+
+ void addToPath(QPainterPath &path);
+};
+QML_DECLARE_TYPE(QFxPathLine);
+
+class Q_DECLARATIVE_EXPORT QFxPathQuad : public QFxCurve
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal controlX READ controlX WRITE setControlX NOTIFY changed)
+ Q_PROPERTY(qreal controlY READ controlY WRITE setControlY NOTIFY changed)
+public:
+ QFxPathQuad(QObject *parent=0) : QFxCurve(parent), _controlX(0), _controlY(0) {}
+
+ qreal controlX() const;
+ void setControlX(qreal x);
+
+ qreal controlY() const;
+ void setControlY(qreal y);
+
+ void addToPath(QPainterPath &path);
+
+private:
+ qreal _controlX;
+ qreal _controlY;
+};
+QML_DECLARE_TYPE(QFxPathQuad);
+
+class Q_DECLARATIVE_EXPORT QFxPathCubic : public QFxCurve
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal control1X READ control1X WRITE setControl1X NOTIFY changed)
+ Q_PROPERTY(qreal control1Y READ control1Y WRITE setControl1Y NOTIFY changed)
+ Q_PROPERTY(qreal control2X READ control2X WRITE setControl2X NOTIFY changed)
+ Q_PROPERTY(qreal control2Y READ control2Y WRITE setControl2Y NOTIFY changed)
+public:
+ QFxPathCubic(QObject *parent=0) : QFxCurve(parent), _control1X(0), _control1Y(0), _control2X(0), _control2Y(0) {}
+
+ qreal control1X() const;
+ void setControl1X(qreal x);
+
+ qreal control1Y() const;
+ void setControl1Y(qreal y);
+
+ qreal control2X() const;
+ void setControl2X(qreal x);
+
+ qreal control2Y() const;
+ void setControl2Y(qreal y);
+
+ void addToPath(QPainterPath &path);
+
+private:
+ int _control1X;
+ int _control1Y;
+ int _control2X;
+ int _control2Y;
+};
+QML_DECLARE_TYPE(QFxPathCubic);
+
+class Q_DECLARATIVE_EXPORT QFxPathPercent : public QFxPathElement
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal value READ value WRITE setValue)
+public:
+ QFxPathPercent(QObject *parent=0) : QFxPathElement(parent) {}
+
+ qreal value() const;
+ void setValue(qreal value);
+
+private:
+ qreal _value;
+};
+QML_DECLARE_TYPE(QFxPathPercent);
+
+class QFxPathPrivate;
+class Q_DECLARATIVE_EXPORT QFxPath : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+
+ Q_INTERFACES(QmlParserStatus);
+ Q_PROPERTY(QList<QFxPathElement *>* pathElements READ pathElements)
+ Q_PROPERTY(qreal startX READ startX WRITE setStartX)
+ Q_PROPERTY(qreal startY READ startY WRITE setStartY)
+ Q_CLASSINFO("DefaultProperty", "pathElements")
+ Q_INTERFACES(QmlParserStatus)
+public:
+ QFxPath(QObject *parent=0);
+ ~QFxPath();
+
+ QList<QFxPathElement *>* pathElements();
+
+ qreal startX() const;
+ void setStartX(qreal x);
+
+ qreal startY() const;
+ void setStartY(qreal y);
+
+ QPainterPath path() const;
+ QStringList attributes() const;
+ qreal attributeAt(const QString &, qreal) const;
+ QPointF pointAt(qreal) const;
+
+Q_SIGNALS:
+ void changed();
+
+protected:
+ virtual void componentComplete();
+ QFxPath(QFxPathPrivate &dd, QObject *parent);
+
+private Q_SLOTS:
+ void processPath();
+
+private:
+ struct AttributePoint {
+ AttributePoint() : percent(0), scale(1), origpercent(0) {}
+ AttributePoint(const AttributePoint &other)
+ : percent(other.percent), scale(other.scale), origpercent(other.origpercent), values(other.values) {}
+ AttributePoint &operator=(const AttributePoint &other) {
+ percent = other.percent; scale = other.scale; origpercent = other.origpercent; values = other.values; return *this;
+ }
+ qreal percent; //massaged percent along the painter path
+ qreal scale;
+ qreal origpercent; //'real' percent along the painter path
+ QHash<QString, qreal> values;
+ };
+
+ void interpolate(int idx, const QString &name, qreal value);
+ void endpoint(const QString &name);
+ void createPointCache() const;
+
+private:
+ Q_DISABLE_COPY(QFxPath)
+ Q_DECLARE_PRIVATE(QFxPath)
+};
+QML_DECLARE_TYPE(QFxPath);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXPATH_H
diff --git a/src/declarative/fx/qfxpath_p.h b/src/declarative/fx/qfxpath_p.h
new file mode 100644
index 0000000..d4a419a
--- /dev/null
+++ b/src/declarative/fx/qfxpath_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXPATH_P_H
+#define QFXPATH_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/qobject_p.h"
+#include "qfxpath.h"
+#include "qml.h"
+
+
+QT_BEGIN_NAMESPACE
+class QFxPathPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QFxPath)
+
+public:
+ QFxPathPrivate() : startX(0), startY(0) { }
+
+ QPainterPath _path;
+ QList<QFxPathElement*> _pathElements;
+ mutable QVector<QPointF> _pointCache;
+ QList<QFxPath::AttributePoint> _attributePoints;
+ QStringList _attributes;
+ int startX;
+ int startY;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/fx/qfxpathview.cpp b/src/declarative/fx/qfxpathview.cpp
new file mode 100644
index 0000000..b7215cf
--- /dev/null
+++ b/src/declarative/fx/qfxpathview.cpp
@@ -0,0 +1,889 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <math.h>
+#include <QDebug>
+#include <QEvent>
+#include "qmlbindablevalue.h"
+#include "qmlstate.h"
+#include "qlistmodelinterface.h"
+#include "qmlopenmetaobject.h"
+
+#include "qfxpathview.h"
+#include "qfxpathview_p.h"
+#include <QGraphicsSceneEvent>
+
+static const int FlickThreshold = 5;
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(QFxPathView,PathView);
+
+class QFxPathViewAttached : public QObject
+{
+ Q_OBJECT
+public:
+ QFxPathViewAttached(QObject *parent)
+ : QObject(parent), mo(new QmlOpenMetaObject(this))
+ {
+ }
+
+ ~QFxPathViewAttached()
+ {
+ QFxPathView::attachedProperties.remove(parent());
+ }
+
+ QVariant value(const QByteArray &name) const
+ {
+ return mo->value(name);
+ }
+ void setValue(const QByteArray &name, const QVariant &val)
+ {
+ mo->setValue(name, val);
+ }
+
+private:
+ QmlOpenMetaObject *mo;
+};
+
+
+/*!
+ \internal
+ \class QFxPathView
+ \brief The QFxPathView class lays out items provided by a model on a path.
+
+ \ingroup group_views
+
+ The model must be a \l QListModelInterface subclass.
+
+ \sa QFxPath
+*/
+
+/*!
+ \qmlclass PathView
+ \brief The PathView element lays out model-provided items on a path.
+ \inherits Item
+
+ The model is typically provided by a QAbstractListModel "C++ model object", but can also be created directly in QML.
+
+ The items are laid out along a path defined by a \l Path and may be flicked to scroll.
+
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 0
+
+ \image pathview.gif
+
+ \sa Path
+*/
+
+QFxPathView::QFxPathView(QFxItem *parent)
+ : QFxItem(*(new QFxPathViewPrivate), parent)
+{
+ Q_D(QFxPathView);
+ d->init();
+}
+
+QFxPathView::QFxPathView(QFxPathViewPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxPathView);
+ d->init();
+}
+
+QFxPathView::~QFxPathView()
+{
+}
+
+/*!
+ \qmlproperty model PathView::model
+ This property holds the model providing data for the view.
+
+ The model provides a set of data that is used to create the items for the view.
+ For large or dynamic datasets the model is usually provided by a C++ model object.
+ Models can also be created directly in XML, using the ListModel element.
+*/
+
+/*!
+ \property QFxPathView::model
+ \brief the model providing data for the view.
+
+ The model must be either a \l QListModelInterface or
+ \l QFxVisualItemModel subclass.
+*/
+QVariant QFxPathView::model() const
+{
+ Q_D(const QFxPathView);
+ return d->modelVariant;
+}
+
+void QFxPathView::setModel(const QVariant &model)
+{
+ Q_D(QFxPathView);
+ 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(itemCreated(int, QFxItem*)), this, SLOT(itemCreated(int,QFxItem*)));
+ for (int i=0; i<d->items.count(); i++){
+ QFxItem *p = d->items[i];
+ d->model->release(p);
+ }
+ d->items.clear();
+ }
+
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QFxVisualItemModel *vim = 0;
+ if (object && (vim = qobject_cast<QFxVisualItemModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QFxVisualItemModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ d->model->setModel(model);
+ }
+ if (d->model) {
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(itemCreated(int, QFxItem*)), this, SLOT(itemCreated(int,QFxItem*)));
+ }
+ d->firstIndex = 0;
+ d->pathOffset = 0;
+ d->regenerate();
+ d->fixOffset();
+}
+
+/*!
+ \qmlproperty int PathView::count
+ This property holds the number of items in the model.
+*/
+int QFxPathView::count() const
+{
+ Q_D(const QFxPathView);
+ return d->model ? d->model->count() : 0;
+}
+
+/*!
+ \qmlproperty Path PathView::path
+ \default
+ This property holds the path used to lay out the items.
+ For more information see the \l Path documentation.
+*/
+QFxPath *QFxPathView::path() const
+{
+ Q_D(const QFxPathView);
+ return d->path;
+}
+
+void QFxPathView::setPath(QFxPath *path)
+{
+ Q_D(QFxPathView);
+ d->path = path;
+ connect(d->path, SIGNAL(changed()), this, SLOT(refill()));
+ d->regenerate();
+}
+
+/*!
+ \qmlproperty int PathView::currentIndex
+ This property holds the index of the current item.
+*/
+int QFxPathView::currentIndex() const
+{
+ Q_D(const QFxPathView);
+ return d->currentIndex;
+}
+
+void QFxPathView::setCurrentIndex(int idx)
+{
+ Q_D(QFxPathView);
+ if (d->model && d->model->count())
+ idx = qAbs(idx % d->model->count());
+ if (d->model && idx != d->currentIndex) {
+ d->currentIndex = idx;
+ d->snapToCurrent();
+ int itemIndex = (idx - d->firstIndex + d->model->count()) % d->model->count();
+ if (itemIndex < d->items.count())
+ d->items.at(itemIndex)->setFocus(true);
+ emit currentIndexChanged();
+ }
+}
+
+/*!
+ \qmlproperty real PathView::offset
+
+ The offset specifies how far along the path the items are from their initial positions.
+*/
+qreal QFxPathView::offset() const
+{
+ Q_D(const QFxPathView);
+ return d->_offset;
+}
+
+void QFxPathView::setOffset(qreal offset)
+{
+ Q_D(QFxPathView);
+ d->setOffset(offset);
+ d->updateCurrent();
+}
+
+void QFxPathViewPrivate::setOffset(qreal o)
+{
+ Q_Q(QFxPathView);
+ if (_offset != o) {
+ _offset = fmod(o, 100.0);
+ if (_offset < 0)
+ _offset = 100.0 + _offset;
+ q->refill();
+ }
+}
+
+/*!
+ \qmlproperty real PathView::snapPosition
+ This property holds the position (0-100) the current item snaps to.
+*/
+
+/*!
+ \property QFxPathView::snapPosition
+ \brief sets the position (0-100) the current item snaps to.
+
+ This property determines the position the nearest item will snap to.
+*/
+qreal QFxPathView::snapPosition() const
+{
+ Q_D(const QFxPathView);
+ return d->snapPos;
+}
+
+void QFxPathView::setSnapPosition(qreal pos)
+{
+ Q_D(QFxPathView);
+ d->snapPos = pos/100;
+ d->fixOffset();
+}
+
+/*!
+ \qmlproperty real PathView::dragMargin
+ This property holds the maximum distance from the path that initiate mouse dragging.
+
+ By default the path can only be dragged by clicking on an item. If
+ dragMargin is greater than zero, a drag can be initiated by clicking
+ within dragMargin pixels of the path.
+*/
+qreal QFxPathView::dragMargin() const
+{
+ Q_D(const QFxPathView);
+ return d->dragMargin;
+}
+
+void QFxPathView::setDragMargin(qreal dragMargin)
+{
+ Q_D(QFxPathView);
+ d->dragMargin = dragMargin;
+}
+
+/*!
+ \qmlproperty component PathView::delegate
+
+ The delegate provides a template describing what each item in the view should look and act like.
+
+ Here is an example delegate:
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+*/
+
+/*!
+ \property QFxPathView::delegate
+ \brief the component to use to render the items.
+
+ The delegate is a component that the view will instantiate and destroy
+ as needed to display the items.
+
+*/
+QmlComponent *QFxPathView::delegate() const
+{
+ Q_D(const QFxPathView);
+ return d->model ? d->model->delegate() : 0;
+}
+
+void QFxPathView::setDelegate(QmlComponent *c)
+{
+ Q_D(QFxPathView);
+ if (!d->ownModel) {
+ d->model = new QFxVisualItemModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ d->model->setDelegate(c);
+ d->regenerate();
+}
+
+/*!
+ \property QFxPathView::pathItemCount
+ \brief the number of items visible on the path at any one time
+ */
+/*!
+ \qmlproperty int PathView::pathItemCount
+ This property holds the number of items visible on the path at any one time
+*/
+int QFxPathView::pathItemCount() const
+{
+ Q_D(const QFxPathView);
+ return d->pathItems;
+}
+
+void QFxPathView::setPathItemCount(int i)
+{
+ Q_D(QFxPathView);
+ if (i == d->pathItems)
+ return;
+ d->pathItems = i;
+ d->regenerate();
+}
+
+QPointF QFxPathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) const
+{
+ //XXX maybe do recursively at increasing resolution.
+ qreal mindist = 1e10; // big number
+ QPointF nearPoint = path->pointAt(0);
+ qreal nearPc = 0;
+ for (qreal i=1; i < 1000; i++) {
+ QPointF pt = path->pointAt(i/1000.0);
+ QPointF diff = pt - point;
+ qreal dist = diff.x()*diff.x() + diff.y()*diff.y();
+ if (dist < mindist) {
+ nearPoint = pt;
+ nearPc = i;
+ mindist = dist;
+ }
+ }
+
+ if (nearPercent)
+ *nearPercent = nearPc / 10.0;
+
+ return nearPoint;
+}
+
+
+void QFxPathView::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxPathView);
+ if (!d->items.count())
+ return;
+ QPointF scenePoint = mapToScene(event->pos());
+ int idx = 0;
+ for (; idx < d->items.count(); ++idx) {
+ QRectF rect = d->items.at(idx)->boundingRect();
+ rect = d->items.at(idx)->mapToScene(rect);
+ if (rect.contains(scenePoint))
+ break;
+ }
+ if (idx == d->items.count() && d->dragMargin == 0.) // didn't click on an item
+ return;
+
+ d->startPoint = d->pointNear(event->pos(), &d->startPc);
+ if (idx == d->items.count()) {
+ qreal distance = qAbs(event->pos().x() - d->startPoint.x()) + qAbs(event->pos().y() - d->startPoint.y());
+ if (distance > d->dragMargin)
+ return;
+ }
+
+ d->stealMouse = false;
+ d->lastElapsed = 0;
+ d->lastDist = 0;
+ d->lastPosTime.start();
+ d->tl.clear();
+}
+
+void QFxPathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxPathView);
+ if (d->lastPosTime.isNull())
+ return;
+
+ if (!d->stealMouse) {
+ QPointF delta = event->pos() - d->startPoint;
+ if (qAbs(delta.x()) > FlickThreshold && qAbs(delta.y()) > FlickThreshold)
+ d->stealMouse = true;
+ }
+
+ if (d->stealMouse) {
+ d->moveReason = QFxPathViewPrivate::Mouse;
+ qreal newPc;
+ d->pointNear(event->pos(), &newPc);
+ qreal diff = newPc - d->startPc;
+ if (diff) {
+ setOffset(d->_offset + diff);
+
+ if (diff > 50)
+ diff -= 100;
+ else if (diff < -50)
+ diff += 100;
+
+ d->lastElapsed = d->lastPosTime.restart();
+ d->lastDist = diff;
+ d->startPc = newPc;
+ }
+ }
+}
+
+void QFxPathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *)
+{
+ Q_D(QFxPathView);
+ if (d->lastPosTime.isNull())
+ return;
+
+ qreal elapsed = qreal(d->lastElapsed + d->lastPosTime.elapsed()) / 1000.;
+ qreal velocity = elapsed > 0. ? d->lastDist / elapsed : 0;
+ if (d->model && d->model->count() && qAbs(velocity) > 5) {
+ if (velocity > 100)
+ velocity = 100;
+ else if (velocity < -100)
+ velocity = -100;
+ qreal inc = fmod(d->_offset - d->snapPos, 100.0 / d->model->count());
+ qreal dist = qAbs(velocity/2 - fmod(velocity/2, 100.0 / d->model->count()) - inc);
+ d->moveOffset.setValue(d->_offset);
+ d->tl.accel(d->moveOffset, velocity, 10, dist);
+ d->tl.execute(d->fixupOffsetEvent);
+ } else {
+ d->fixOffset();
+ }
+
+ d->lastPosTime = QTime();
+ d->stealMouse = false;
+}
+
+bool QFxPathView::sendMouseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxPathView);
+ QGraphicsSceneMouseEvent mouseEvent(event->type());
+ QRectF myRect = mapToScene(QRectF(0, 0, width(), height()));
+ QFxItem *grabber = static_cast<QFxItem*>(mouseGrabberItem());
+ if ((d->stealMouse || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) {
+ 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:
+ mouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMousePress:
+ mousePressEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ mouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = static_cast<QFxItem*>(mouseGrabberItem());
+ if (grabber && d->stealMouse && !grabber->keepMouseGrab())
+ mouseGrabberItem()->ungrabMouse();
+
+ return d->stealMouse;
+ } else if (!d->lastPosTime.isNull()) {
+ d->lastPosTime = QTime();
+ }
+ return false;
+}
+
+bool QFxPathView::mouseFilter(QGraphicsSceneMouseEvent *e)
+{
+ if (!isVisible())
+ return false;
+
+ switch (e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ {
+ bool ret = sendMouseEvent(e);
+ if (e->type() == QEvent::GraphicsSceneMouseRelease)
+ return ret;
+ break;
+ }
+ default:
+ break;
+ }
+
+ return false;
+}
+
+void QFxPathViewPrivate::regenerate()
+{
+ Q_Q(QFxPathView);
+ for (int i=0; i<items.count(); i++){
+ QFxItem *p = items[i];
+ model->release(p);
+ }
+ items.clear();
+
+ if (!isValid())
+ return;
+
+ if (firstIndex >= model->count())
+ firstIndex = model->count()-1;
+ if (pathOffset >= model->count())
+ pathOffset = model->count()-1;
+
+ int numItems = pathItems >= 0 ? pathItems : model->count();
+ for (int i=0; i < numItems && i < model->count(); ++i){
+ QFxItem *item = getItem((i + firstIndex) % model->count());
+ if (!item) {
+ qWarning() << "PathView: Cannot create item, index" << (i + firstIndex) % model->count();
+ return;
+ }
+ items.append(item);
+ item->setZ(i);
+ }
+ q->refill();
+}
+
+void QFxPathViewPrivate::updateItem(QFxItem *item, qreal percent)
+{
+ if (QObject *obj = QFxPathView::qmlAttachedProperties(item)) {
+ foreach(const QString &attr, path->attributes())
+ static_cast<QFxPathViewAttached *>(obj)->setValue(attr.toLatin1(), path->attributeAt(attr, percent));
+ }
+ QPointF pf = path->pointAt(percent);
+ item->setX(pf.x() - item->width()*item->scale()/2);
+ item->setY(pf.y() - item->height()*item->scale()/2);
+}
+
+void QFxPathView::refill()
+{
+ Q_D(QFxPathView);
+ if (!d->isValid())
+ return;
+
+ QList<qreal> positions;
+ for (int i=0; i<d->items.count(); i++){
+ qreal percent = i * (100. / d->items.count());
+ percent = percent + d->_offset;
+ percent = fmod(percent,100.);
+ positions << qAbs(percent/100.0);
+ }
+
+ if (d->pathItems==-1) {
+ for (int i=0; i<positions.count(); i++)
+ d->updateItem(d->items.at(i), positions[i]);
+ return;
+ }
+
+ QList<qreal> rotatedPositions;
+ for (int i=0; i<d->items.count(); i++)
+ rotatedPositions << positions[(i + d->pathOffset + d->items.count()) % d->items.count()];
+
+ int wrapIndex= -1;
+ for (int i=0; i<d->items.count()-1; i++) {
+ if (rotatedPositions[i] > rotatedPositions[i+1]){
+ wrapIndex = i;
+ break;
+ }
+ }
+ if (wrapIndex != -1 ){
+ //A wraparound has occured
+ if (wrapIndex < d->items.count()/2){
+ while(wrapIndex-- >= 0){
+ QFxItem* p = d->items.takeFirst();
+ d->updateItem(p, 0.0);
+ d->model->release(p);
+ d->firstIndex++;
+ d->firstIndex %= d->model->count();
+ int index = (d->firstIndex + d->items.count())%d->model->count();
+ d->items << d->getItem(index);
+ d->items.last()->setZ(wrapIndex);
+ d->pathOffset++;
+ d->pathOffset=d->pathOffset % d->items.count();
+ }
+ } else {
+ while(wrapIndex++ < d->items.count()-1){
+ QFxItem* p = d->items.takeLast();
+ d->updateItem(p, 1.0);
+ d->model->release(p);
+ d->firstIndex--;
+ if (d->firstIndex < 0)
+ d->firstIndex = d->model->count() - 1;
+ d->items.prepend(d->getItem(d->firstIndex));
+ d->items.first()->setZ(d->firstIndex);
+ d->pathOffset--;
+ if (d->pathOffset < 0)
+ d->pathOffset = d->items.count() - 1;
+ }
+ }
+ for (int i=0; i<d->items.count(); i++)
+ rotatedPositions[i] = positions[(i + d->pathOffset + d->items.count())
+ % d->items.count()];
+ }
+ for (int i=0; i<d->items.count(); i++)
+ d->updateItem(d->items.at(i), rotatedPositions[i]);
+}
+
+void QFxPathView::itemsInserted(int modelIndex, int count)
+{
+ //XXX support animated insertion
+ Q_D(QFxPathView);
+ if (!d->isValid())
+ return;
+ if (d->pathItems == -1) {
+ for (int i = 0; i < count; ++i) {
+ QFxItem *item = d->getItem(modelIndex + i);
+ item->setZ(modelIndex + i);
+ d->items.insert(modelIndex + i, item);
+ }
+ refill();
+ } else {
+ //XXX This is pretty heavy handed until we reference count items.
+ d->regenerate();
+ }
+
+ // make sure the current item is still at the snap position
+ int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count();
+ itemIndex += d->pathOffset;
+ itemIndex %= d->items.count();
+ qreal targetOffset = fmod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), 100);
+
+ if (targetOffset < 0)
+ targetOffset = 100.0 + targetOffset;
+ if (targetOffset != d->_offset)
+ d->moveOffset.setValue(targetOffset);
+}
+
+void QFxPathView::itemsRemoved(int modelIndex, int count)
+{
+ //XXX support animated removal
+ Q_D(QFxPathView);
+ if (!d->isValid())
+ return;
+ if (d->pathItems == -1) {
+ for (int i = 0; i < count; ++i) {
+ QFxItem* p = d->items.takeAt(modelIndex);
+ d->model->release(p);
+ }
+ d->snapToCurrent();
+ refill();
+ } else {
+ d->regenerate();
+ }
+
+ if (d->model->count() == 0) {
+ d->currentIndex = -1;
+ d->moveOffset.setValue(0);
+ return;
+ }
+
+ // make sure the current item is still at the snap position
+ if (d->currentIndex >= d->model->count())
+ d->currentIndex = d->model->count() - 1;
+ int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count();
+ itemIndex += d->pathOffset;
+ itemIndex %= d->items.count();
+ qreal targetOffset = fmod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), 100);
+
+ if (targetOffset < 0)
+ targetOffset = 100.0 + targetOffset;
+ if (targetOffset != d->_offset)
+ d->moveOffset.setValue(targetOffset);
+}
+
+void QFxPathView::itemCreated(int index, QFxItem *item)
+{
+ Q_D(QFxPathView);
+ if (d->requestedIndex != index) {
+ item->setItemParent(this);
+ d->updateItem(item, index < d->firstIndex ? 0.0 : 1.0);
+ }
+}
+
+void QFxPathView::destroyingItem(QFxItem *item)
+{
+}
+
+void QFxPathView::ticked()
+{
+ Q_D(QFxPathView);
+ d->updateCurrent();
+}
+
+// find the item closest to the snap position
+int QFxPathViewPrivate::calcCurrentIndex()
+{
+ int current = -1;
+ if (model && items.count()) {
+ _offset = fmod(_offset, 100.0);
+ if (_offset < 0)
+ _offset += 100.0;
+
+ if (pathItems == -1) {
+ qreal delta = fmod(_offset - snapPos, 100.0);
+ if (delta < 0)
+ delta = 100.0 + delta;
+ int ii = model->count() - qRound(delta * model->count() / 100);
+ if (ii < 0)
+ ii = 0;
+ current = ii;
+ } else {
+ qreal bestDiff=1e9;
+ int bestI=-1;
+ for (int i=0; i<items.count(); i++){
+ qreal percent = i * (100. / items.count());
+ percent = percent + _offset;
+ percent = fmod(percent,100.);
+ qreal diff = qAbs(snapPos - (percent/100.0));
+ if (diff < bestDiff){
+ bestDiff = diff;
+ bestI = i;
+ }
+ }
+ int modelIndex = (bestI - pathOffset + items.count())%items.count();
+ modelIndex += firstIndex;
+ current = modelIndex;
+ }
+ current = qAbs(current % model->count());
+ }
+
+ return current;
+}
+
+void QFxPathViewPrivate::updateCurrent()
+{
+ Q_Q(QFxPathView);
+ if (moveReason != Mouse)
+ return;
+ int idx = calcCurrentIndex();
+ if (model && idx != currentIndex) {
+ currentIndex = idx;
+ int itemIndex = (idx - firstIndex + model->count()) % model->count();
+ if (itemIndex < items.count())
+ items.at(itemIndex)->setFocus(true);
+ emit q->currentIndexChanged();
+ }
+}
+
+void QFxPathViewPrivate::fixOffset()
+{
+ Q_Q(QFxPathView);
+ if (model && items.count()) {
+ int curr = calcCurrentIndex();
+ if (curr != currentIndex)
+ q->setCurrentIndex(curr);
+ else
+ snapToCurrent();
+ }
+}
+
+void QFxPathViewPrivate::snapToCurrent()
+{
+ if (!model || model->count() <= 0)
+ return;
+
+ int itemIndex = (currentIndex - firstIndex + model->count()) % model->count();
+
+ //Rounds is the number of times round to make the current item visible
+ int rounds = itemIndex / items.count();
+ int otherWayRounds = (model->count() - (itemIndex)) / items.count() + 1;
+ if (otherWayRounds < rounds)
+ rounds = -otherWayRounds;
+
+ itemIndex += pathOffset;
+ itemIndex %= items.count();
+ qreal targetOffset = fmod(100 + (snapPos*100) - 100.0 * itemIndex / items.count(), 100);
+
+ if (targetOffset < 0)
+ targetOffset = 100.0 + targetOffset;
+ if (targetOffset == _offset && rounds == 0)
+ return;
+
+ moveReason = Other;
+ tl.clear();
+ moveOffset.setValue(_offset);
+
+ if (rounds!=0){
+ //Compensate if the targetOffset would bring the target it from off the screen
+ qreal distance = targetOffset - _offset;
+ if (distance <= -50)
+ rounds--;
+ if (distance > 50)
+ rounds++;
+ tl.move(moveOffset, targetOffset + 100.0*(-rounds), QEasingCurve(QEasingCurve::InOutQuad),
+ int(100*items.count()*qMax((qreal)(2.0/items.count()),(qreal)qAbs(rounds))));
+ tl.execute(fixupOffsetEvent);
+ return;
+ }
+
+ if (targetOffset - _offset > 50.0) {
+ qreal distance = 100 - targetOffset + _offset;
+ tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::OutQuad), int(200 * _offset / distance));
+ tl.set(moveOffset, 100.0);
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InQuad), int(200 * (100-targetOffset) / distance));
+ } else if (targetOffset - _offset <= -50.0) {
+ qreal distance = 100 - _offset + targetOffset;
+ tl.move(moveOffset, 100.0, QEasingCurve(QEasingCurve::OutQuad), int(200 * (100-_offset) / distance));
+ tl.set(moveOffset, 0.0);
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InQuad), int(200 * targetOffset / distance));
+ } else {
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), 200);
+ }
+}
+
+QHash<QObject*, QObject*> QFxPathView::attachedProperties;
+QObject *QFxPathView::qmlAttachedProperties(QObject *obj)
+{
+ QObject *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QFxPathViewAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+}
+
+QT_END_NAMESPACE
+
+#include "qfxpathview.moc"
diff --git a/src/declarative/fx/qfxpathview.h b/src/declarative/fx/qfxpathview.h
new file mode 100644
index 0000000..2ecd04e
--- /dev/null
+++ b/src/declarative/fx/qfxpathview.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXPATHVIEW_H
+#define QFXPATHVIEW_H
+
+#include <qfxitem.h>
+#include <qfxpath.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QListModelInterface;
+class QFxPathViewPrivate;
+class Q_DECLARATIVE_EXPORT QFxPathView : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_PROPERTY(QFxPath *path READ path WRITE setPath)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(qreal offset READ offset WRITE setOffset NOTIFY offsetChanged)
+ Q_PROPERTY(qreal snapPosition READ snapPosition WRITE setSnapPosition)
+ Q_PROPERTY(qreal dragMargin READ dragMargin WRITE setDragMargin)
+ Q_PROPERTY(int count READ count)
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(int pathItemCount READ pathItemCount WRITE setPathItemCount)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+public:
+ QFxPathView(QFxItem *parent=0);
+ virtual ~QFxPathView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QFxPath *path() const;
+ void setPath(QFxPath *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ qreal offset() const;
+ void setOffset(qreal offset);
+
+ qreal snapPosition() const;
+ void setSnapPosition(qreal pos);
+
+ qreal dragMargin() const;
+ void setDragMargin(qreal margin);
+
+ int count() const;
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ int pathItemCount() const;
+ void setPathItemCount(int);
+
+ static QObject *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void currentIndexChanged();
+ void offsetChanged();
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
+ bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
+ bool mouseFilter(QGraphicsSceneMouseEvent *e);
+
+private Q_SLOTS:
+ void refill();
+ void ticked();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemCreated(int index, QFxItem *item);
+ void destroyingItem(QFxItem *item);
+
+protected:
+ QFxPathView(QFxPathViewPrivate &dd, QFxItem *parent);
+
+private:
+ friend class QFxPathViewAttached;
+ static QHash<QObject*, QObject*> attachedProperties;
+ Q_DISABLE_COPY(QFxPathView)
+ Q_DECLARE_PRIVATE(QFxPathView)
+};
+QML_DECLARE_TYPE(QFxPathView);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXPATHVIEW_H
diff --git a/src/declarative/fx/qfxpathview_p.h b/src/declarative/fx/qfxpathview_p.h
new file mode 100644
index 0000000..358daf6
--- /dev/null
+++ b/src/declarative/fx/qfxpathview_p.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXPATHVIEW_P_H
+#define QFXPATHVIEW_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 "qdatetime.h"
+#include "qfxpathview.h"
+#include "qfxitem_p.h"
+#include "qfxvisualitemmodel.h"
+#include "qml.h"
+#include "qmltimelinevalueproxy.h"
+#include "private/qmlanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+typedef struct PathViewItem{
+ int index;
+ QFxItem* item;
+}PathViewItem;
+
+class QFxPathViewPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxPathView)
+
+public:
+ QFxPathViewPrivate()
+ : path(0), currentIndex(0), startPc(0), lastDist(0)
+ , lastElapsed(0), stealMouse(false), ownModel(false), activeItem(0)
+ , snapPos(0), dragMargin(0), moveOffset(this, &QFxPathViewPrivate::setOffset)
+ , firstIndex(0), pathItems(-1), pathOffset(0), requestedIndex(-1), model(0)
+ , moveReason(Other)
+ {
+ fixupOffsetEvent = QmlTimeLineEvent::timeLineEvent<QFxPathViewPrivate, &QFxPathViewPrivate::fixOffset>(&moveOffset, this);
+ }
+
+ void init()
+ {
+ Q_Q(QFxPathView);
+ _offset = 0;
+ q->setAcceptedMouseButtons(Qt::NoButton);
+ q->setOptions(QSimpleCanvasItem::MouseFilter | QSimpleCanvasItem::MouseEvents | QSimpleCanvasItem::IsFocusRealm);
+ q->connect(&tl, SIGNAL(updated()), q, SLOT(ticked()));
+ }
+
+ QFxItem *getItem(int modelIndex) {
+ Q_Q(QFxPathView);
+ requestedIndex = modelIndex;
+ QFxItem *item = model->item(modelIndex);
+ if (item)
+ item->setItemParent(q);
+ requestedIndex = -1;
+ return item;
+ }
+
+ bool isValid() const {
+ return model && model->count() > 0 && model->delegate() && path;
+ }
+
+ int calcCurrentIndex();
+ void updateCurrent();
+ void fixOffset();
+ void setOffset(qreal offset);
+ void regenerate();
+ void updateItem(QFxItem *, qreal);
+ void snapToCurrent();
+ QPointF pointNear(const QPointF &point, qreal *nearPercent=0) const;
+
+ QFxPath *path;
+ int currentIndex;
+ qreal startPc;
+ QPointF startPoint;
+ qreal lastDist;
+ int lastElapsed;
+ qreal _offset;
+ bool stealMouse : 1;
+ bool ownModel : 1;
+ QTime lastPosTime;
+ QPointF lastPos;
+ QFxItem *activeItem;
+ qreal snapPos;
+ qreal dragMargin;
+ QmlTimeLine tl;
+ QmlTimeLineValueProxy<QFxPathViewPrivate> moveOffset;
+ QmlTimeLineEvent fixupOffsetEvent;
+ int firstIndex;
+ int pathItems;
+ int pathOffset;
+ int requestedIndex;
+ QList<QFxItem *> items;
+ QFxVisualItemModel *model;
+ QVariant modelVariant;
+ enum MovementReason { Other, Key, Mouse };
+ MovementReason moveReason;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/fx/qfxpixmap.cpp b/src/declarative/fx/qfxpixmap.cpp
new file mode 100644
index 0000000..0e5a10f
--- /dev/null
+++ b/src/declarative/fx/qfxpixmap.cpp
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxpixmap.h"
+#include <QHash>
+#include <QNetworkReply>
+#include <qfxperf.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QFile>
+
+
+QT_BEGIN_NAMESPACE
+class QFxPixmapCacheItem;
+typedef QHash<QString, QFxPixmapCacheItem *> QFxPixmapCache;
+static QFxPixmapCache qfxPixmapCache;
+
+class QFxPixmapCacheItem
+{
+public:
+ QFxPixmapCacheItem() : reply(0), refCount(1) {}
+ QString key;
+ QNetworkReply *reply;
+#if defined(QFX_RENDER_OPENGL)
+ QImage image;
+#else
+ QImage image;
+ QImage opaqueImage;
+#endif
+
+ int refCount;
+ void addRef() { ++refCount; }
+ void release() { Q_ASSERT(refCount > 0); --refCount; if (refCount == 0) { qfxPixmapCache.remove(key); delete this; } }
+};
+
+static QFxPixmapCacheItem qfxPixmapCacheDummyItem;
+
+class QFxPixmapPrivate
+{
+public:
+ QFxPixmapPrivate()
+ : opaque(false), pixmap(&qfxPixmapCacheDummyItem) { pixmap->addRef(); }
+
+ bool opaque;
+ QFxPixmapCacheItem *pixmap;
+};
+
+/*!
+ \internal
+ \class QFxPixmap
+ \ingroup group_utility
+ \brief Enacapsultes a pixmap for QFx items.
+
+ This class is NOT reentrant.
+ The pixmap cache will grow indefinately.
+ */
+QFxPixmap::QFxPixmap()
+: d(new QFxPixmapPrivate)
+{
+}
+
+QFxPixmap::QFxPixmap(const QUrl &url)
+: d(new QFxPixmapPrivate)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::PixmapLoad> perf;
+#endif
+ QString key = url.toString();
+ QFxPixmapCache::Iterator iter = qfxPixmapCache.find(key);
+ if (iter == qfxPixmapCache.end()) {
+ qWarning() << "QFxPixmap: URL not loaded" << url;
+ } else {
+ QNetworkReply *reply = (*iter)->reply;
+ if (reply) {
+ if (reply->error()) {
+ qWarning() << "Error loading" << url << reply->errorString();
+ } else {
+ (*iter)->image.load(reply, 0);
+ }
+ reply->deleteLater();
+ (*iter)->reply = 0;
+ }
+ (*iter)->addRef();
+ }
+
+ d->pixmap = *iter;
+}
+
+QFxPixmap::QFxPixmap(const QFxPixmap &o)
+: d(new QFxPixmapPrivate)
+{
+ d->opaque = o.d->opaque;
+ o.d->pixmap->addRef();
+ d->pixmap->release();
+ d->pixmap = o.d->pixmap;
+}
+
+QFxPixmap::~QFxPixmap()
+{
+ d->pixmap->release();
+ delete d;
+}
+
+QFxPixmap &QFxPixmap::operator=(const QFxPixmap &o)
+{
+ d->opaque = o.d->opaque;
+ o.d->pixmap->addRef();
+ d->pixmap->release();
+ d->pixmap = o.d->pixmap;
+ return *this;
+}
+
+bool QFxPixmap::isNull() const
+{
+ return d->pixmap->image.isNull();
+}
+
+bool QFxPixmap::opaque() const
+{
+ return d->opaque;
+}
+
+void QFxPixmap::setOpaque(bool o)
+{
+ d->opaque = o;
+}
+
+int QFxPixmap::width() const
+{
+ return d->pixmap->image.width();
+}
+
+int QFxPixmap::height() const
+{
+ return d->pixmap->image.height();
+}
+
+QPixmap QFxPixmap::pixmap() const
+{
+ return QPixmap::fromImage(d->pixmap->image);
+}
+
+void QFxPixmap::setPixmap(const QPixmap &pix)
+{
+ QFxPixmapCache::Iterator iter = qfxPixmapCache.find(QString::number(pix.cacheKey()));
+ if (iter == qfxPixmapCache.end()) {
+ QFxPixmapCacheItem *item = new QFxPixmapCacheItem;
+ item->key = QString::number(pix.cacheKey());
+ if (d->pixmap)
+ d->pixmap->release();
+ d->pixmap = item;
+ d->pixmap->image = pix.toImage();
+ qfxPixmapCache.insert(QString::number(pix.cacheKey()), item);
+ } else {
+ (*iter)->addRef();
+ d->pixmap = *iter;
+ }
+
+#if 0
+ int size = 0;
+ for (QFxPixmapCache::Iterator iter = qfxPixmapCache.begin(); iter != qfxPixmapCache.end(); ++iter) {
+ size += (*iter)->image.width() * (*iter)->image.height();
+ }
+ qWarning() << qfxPixmapCache.count() << size;
+#endif
+}
+
+QFxPixmap::operator const QSimpleCanvasConfig::Image &() const
+{
+#if defined(QFX_RENDER_OPENGL)
+ return d->pixmap->image;
+#else
+ if (d->opaque) {
+ if (!d->pixmap->image.isNull() && d->pixmap->opaqueImage.isNull()) {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::PixmapLoad> perf;
+#endif
+ d->pixmap->opaqueImage = d->pixmap->image.convertToFormat(QPixmap::defaultDepth() == 16 ?
+ QImage::Format_RGB16 :
+ QImage::Format_RGB32);
+ }
+ return d->pixmap->opaqueImage;
+ } else {
+ if (!d->pixmap->image.isNull() && d->pixmap->image.format() != QImage::Format_ARGB32_Premultiplied) {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::PixmapLoad> perf;
+#endif
+ d->pixmap->image = d->pixmap->image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ }
+ return d->pixmap->image;
+ }
+#endif
+}
+
+/*!
+ Starts a network request to load \a url. When the URL is loaded,
+ the given slot is invoked. Note that if the image is already cached,
+ the slot may be invoked immediately.
+
+ Returns a QNetworkReply if the image is not immediately available, otherwise
+ returns 0. The QNetworkReply must not be stored - it may be destroyed at any time.
+*/
+QNetworkReply *QFxPixmap::get(QmlEngine *engine, const QUrl& url, QObject* obj, const char* slot)
+{
+ QString key = url.toString();
+ QFxPixmapCache::Iterator iter = qfxPixmapCache.find(key);
+ if (iter == qfxPixmapCache.end()) {
+ QFxPixmapCacheItem *item = new QFxPixmapCacheItem;
+ item->addRef(); // XXX - will never get deleted. Need to revisit caching
+ item->key = key;
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ if (url.scheme()==QLatin1String("file")) {
+ item->image.load(url.toLocalFile(), 0);
+ } else
+#endif
+ {
+ QNetworkRequest req(url);
+ req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+ item->reply = engine->networkAccessManager()->get(req);
+ }
+ iter = qfxPixmapCache.insert(item->key, item);
+ } else {
+ (*iter)->addRef();
+ }
+ if ((*iter)->reply) {
+ // still loading
+ QObject::connect((*iter)->reply, SIGNAL(finished()), obj, slot);
+ return (*iter)->reply;
+ } else {
+ // already loaded
+ QObject dummy;
+ QObject::connect(&dummy, SIGNAL(destroyed()), obj, slot);
+ }
+
+ return 0;
+}
+
+/*!
+ Stops the given slot being invoked if the given url finishes loading.
+ May also cancel loading (eg. if no other pending request).
+
+ Any connections to the QNetworkReply returned by get() will be
+ disconnected.
+*/
+void QFxPixmap::cancelGet(const QUrl& url, QObject* obj)
+{
+ QString key = url.toString();
+ QFxPixmapCache::Iterator iter = qfxPixmapCache.find(key);
+ if (iter == qfxPixmapCache.end())
+ return;
+ if ((*iter)->reply)
+ QObject::disconnect((*iter)->reply, 0, obj, 0);
+ // XXX - loading not cancelled. Need to revisit caching
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxpixmap.h b/src/declarative/fx/qfxpixmap.h
new file mode 100644
index 0000000..297dba7
--- /dev/null
+++ b/src/declarative/fx/qfxpixmap.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXPIXMAP_H
+#define QFXPIXMAP_H
+
+#include <QString>
+#include <qsimplecanvas.h>
+#include <qfxglobal.h>
+#include <QPixmap>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlEngine;
+class QNetworkReply;
+class QFxPixmapPrivate;
+class Q_DECLARATIVE_EXPORT QFxPixmap
+{
+public:
+ QFxPixmap();
+ QFxPixmap(const QUrl& url); // url must have been passed to QFxPixmap::get, and finished.
+ QFxPixmap(const QFxPixmap &);
+ virtual ~QFxPixmap();
+
+ QFxPixmap &operator=(const QFxPixmap &);
+
+ static QNetworkReply *get(QmlEngine *, const QUrl& url, QObject*, const char* slot);
+ static void cancelGet(const QUrl& url, QObject* obj);
+
+ bool isNull() const;
+
+ bool opaque() const;
+ void setOpaque(bool);
+
+ int width() const;
+ int height() const;
+
+ QPixmap pixmap() const;
+ void setPixmap(const QPixmap &pix);
+
+ operator const QSimpleCanvasConfig::Image &() const;
+
+private:
+ QFxPixmapPrivate *d;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXPIXMAP_H
diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp
new file mode 100644
index 0000000..371aa0c
--- /dev/null
+++ b/src/declarative/fx/qfxrect.cpp
@@ -0,0 +1,864 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxrect.h"
+#include "qfxrect_p.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxPen,Pen);
+
+/*!
+ \internal
+ \class QFxPen
+ \ingroup group_utility
+ \brief The QFxPen class provides a pen used for drawing rect borders on a QFxView.
+
+ Example:
+ \qml
+ Rect { pen.width: 2; pen.color: "red" ... }
+ \endqml
+*/
+
+/*! \property QFxPen::width
+ \brief the width of the pen.
+
+ The default width is 1. If the width is less than 1 the pen is considered invalid
+ and won't be used.
+*/
+
+/*!
+ \property QFxPen::color
+ \brief the color of the pen.
+
+ color is most commonly specified in hexidecimal notation (#RRGGBB)
+ or as an \l {http://www.w3.org/TR/SVG/types.html#ColorKeywords}{SVG color keyword name}
+ (as defined by the World Wide Web Consortium). For example:
+ \qml
+ // rect with green border using hexidecimal notation
+ Rect { pen.color: "#00FF00" }
+
+ // rect with steelblue border using SVG color name
+ Rect { pen.color: "steelblue" }
+ \endqml
+
+ For the full set of ways to specify color, see Qt's QColor::setNamedColor documentation.
+*/
+
+void QFxPen::setColor(const QColor &c)
+{
+ _color = c;
+ emit updated();
+ _valid = _color.alpha() ? true : false;
+}
+
+
+
+QML_DEFINE_TYPE(QFxRect,Rect);
+
+/*!
+ \qmlclass Rect QFxRect
+ \brief The Rect item allows you to add rectangles to a scene.
+ \inherits Item
+
+ A Rect is painted having a solid fill (color) and an optional border (pen).
+ You can also create rounded rectangles using the radius property.
+
+ \qml
+ Rect {
+ width: 100
+ height: 100
+ color: "red"
+ pen.color: "black"
+ pen.width: 5
+ radius: 10
+ }
+ \endqml
+
+ \image declarative-rect.png
+*/
+
+/*!
+ \internal
+ \class QFxRect
+ \brief The QFxRect class provides a rect item that you can add to a QFxView.
+
+ A Rect is painted having a solid fill (color) and an optional border (pen).
+ You can also create rounded rectangles using the radius property.
+
+ \qml
+ Rect {
+ width: 100
+ height: 100
+ color: "red"
+ pen.color: "black"
+ pen.width: 5
+ radius: 10
+ }
+ \endqml
+
+ \image declarative-rect.png
+
+ A QFxRect object can be instantiated in Qml using the tag \l Rect.
+
+ \ingroup group_coreitems
+*/
+QFxRect::QFxRect(QFxItem *parent)
+ : QFxItem(*(new QFxRectPrivate), parent)
+{
+ Q_D(QFxRect);
+ d->init();
+ setOptions(HasContents, true);
+}
+
+QFxRect::QFxRect(QFxRectPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxRect);
+ d->init();
+ setOptions(HasContents, true);
+}
+
+void QFxRect::doUpdate()
+{
+#if defined(QFX_RENDER_QPAINTER)
+ Q_D(QFxRect);
+ d->_rectImage = QSimpleCanvasConfig::Image();
+#endif
+#if defined(QFX_RENDER_OPENGL)
+ Q_D(QFxRect);
+ d->_rectTexture.clear();
+#endif
+ update();
+}
+
+/*!
+ \qmlproperty int Rect::pen.width
+ \qmlproperty color Rect::pen.color
+
+ The pen used to draw the border of the rect.
+*/
+/*!
+ \property QFxRect::pen
+ \brief the pen used to draw the border of the rect.
+*/
+QFxPen *QFxRect::pen()
+{
+ Q_D(QFxRect);
+ return d->pen();
+}
+
+/*!
+ \qmlproperty real Rect::radius
+ This property holds the corner radius used to draw a rounded rect.
+
+ If radius is non-zero, the rect will be painted as a rounded rectangle, otherwise it will be
+ painted as a normal rectangle. The same radius is used by all 4 corners; there is currently
+ no way to specify different radii for different corners.
+*/
+
+/*!
+ \property QFxRect::radius
+ \brief the corner radius used to draw a rounded rect.
+*/
+qreal QFxRect::radius() const
+{
+ Q_D(const QFxRect);
+ return d->_radius;
+}
+
+void QFxRect::setRadius(qreal radius)
+{
+ Q_D(QFxRect);
+ if (d->_radius == radius)
+ return;
+
+ d->_radius = radius;
+#if defined(QFX_RENDER_QPAINTER)
+ d->_rectImage = QSimpleCanvasConfig::Image();
+#elif defined(QFX_RENDER_OPENGL)
+ d->_rectTexture.clear();
+#endif
+ update();
+}
+
+void QFxRect::dump(int depth)
+{
+ Q_D(QFxRect);
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << "QFxRect:" << d->_color;
+ QFxItem::dump(depth);
+}
+
+/*!
+ \qmlproperty color Rect::color
+ This property holds the color used to fill the rect.
+
+ \qml
+ // green rect using hexidecimal notation
+ Rect { color: "#00FF00" }
+
+ // steelblue rect using SVG color name
+ Rect { color: "steelblue" }
+ \endqml
+*/
+
+/*!
+ \property QFxRect::color
+ \brief the color used to fill the rect.
+*/
+QColor QFxRect::color() const
+{
+ Q_D(const QFxRect);
+ return d->_color;
+}
+
+void QFxRect::setColor(const QColor &c)
+{
+ Q_D(QFxRect);
+ if (d->_color == c)
+ return;
+
+ d->_color = c;
+#if defined(QFX_RENDER_QPAINTER)
+ d->_rectImage = QSimpleCanvasConfig::Image();
+#endif
+#if defined(QFX_RENDER_OPENGL)
+ d->_rectTexture.clear();
+#endif
+ update();
+}
+
+
+
+/*!
+ \qmlproperty color Rect::tintColor
+ This property holds The color to tint the rectangle.
+
+ This color will be drawn over the rect's color when the rect is painted. The tint color should usually be mostly transparent, or you will not be able to see the underlying color. The below example provides a slight red tint by having the tint color be pure red which is only 1/16th opaque.
+
+ \qml
+ Rect { x: 0; width: 80; height: 80; color: "lightsteelblue" }
+ Rect { x: 100; width: 80; height: 80; color: "lightsteelblue"; tintColor: "#10FF0000" }
+ \endqml
+ \image declarative-rect_tint.png
+
+ This attribute is not intended to be used with a single color over the lifetime of an user interface. It is most useful when a subtle change is intended to be conveyed due to some event; you can then use the tint color to more effectively tune the visible color.
+*/
+
+/*!
+ \property QFxRect::tintColor
+ \brief The color to tint the rectangle.
+*/
+QColor QFxRect::tintColor() const
+{
+ Q_D(const QFxRect);
+ return d->_tintColor;
+}
+
+void QFxRect::setTintColor(const QColor &c)
+{
+ Q_D(QFxRect);
+ if (d->_tintColor == c)
+ return;
+
+ d->_tintColor = c;
+ update();
+}
+
+QColor QFxRectPrivate::getColor()
+{
+ if (_tintColor.isValid()) {
+ int a = _tintColor.alpha();
+ if (a == 0xFF)
+ return _tintColor;
+ else if (a == 0x00)
+ return _color;
+ else {
+ uint src = _tintColor.rgba();
+ uint dest = _color.rgba();
+
+ uint res = (((a * (src & 0xFF00FF)) +
+ ((0xFF - a) * (dest & 0xFF00FF))) >> 8) & 0xFF00FF;
+ res |= (((a * ((src >> 8) & 0xFF00FF)) +
+ ((0xFF - a) * ((dest >> 8) & 0xFF00FF)))) & 0xFF00FF00;
+ if ((src & 0xFF000000) == 0xFF000000)
+ res |= 0xFF000000;
+
+ return QColor::fromRgba(res);
+ }
+ } else {
+ return _color;
+ }
+}
+
+/*!
+ \qmlproperty color Rect::gradientColor
+ This property holds the color to use at the base of the rectangle and blend upwards.
+
+ This property allows for the easy construction of simple horizontal gradients. Other gradients may by formed by adding rotation to the rect. The gradient will blend linearly from the rect's main color to the color specified for gradient color.
+
+ \qml
+ Rect { y: 0; width: 80; height: 80; color: "lightsteelblue" }
+ Rect { y: 100; width: 80; height: 80; color: "lightsteelblue"; gradientColor="blue" }
+ Rect { rotation: 90; x: 80; y: 200; width: 80; height: 80; color="lightsteelblue"
+ gradientColor: "blue" }
+ // The x offset is needed because the rotation is from the top left corner
+ \endqml
+ \image declarative-rect_gradient.png
+*/
+
+/*!
+ \property QFxRect::gradientColor
+ \brief The color to use at the base of the rectangle and blend upwards.
+*/
+
+QColor QFxRect::gradientColor() const
+{
+ Q_D(const QFxRect);
+ return d->_gradcolor;
+}
+
+void QFxRect::setGradientColor(const QColor &c)
+{
+ Q_D(QFxRect);
+ if (d->_gradcolor == c)
+ return;
+
+ d->_gradcolor = c;
+ update();
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+void QFxRect::generateRoundedRect()
+{
+ Q_D(QFxRect);
+ if (d->_rectImage.isNull()) {
+ d->_rectImage = QImage(d->_radius*2 + 1, d->_radius*2 + 1, QImage::Format_ARGB32_Premultiplied);
+ d->_rectImage.fill(0);
+ QPainter p(&(d->_rectImage));
+ QPen pn(QColor(pen()->color()), pen()->width());
+ p.setRenderHint(QPainter::Antialiasing);
+ p.setPen(pn);
+ p.setBrush(d->_color);
+ p.drawRoundedRect(0, 0, d->_rectImage.width(), d->_rectImage.height(), d->_radius, d->_radius);
+ }
+}
+
+void QFxRect::generateBorderedRect()
+{
+ Q_D(QFxRect);
+ if (d->_rectImage.isNull()) {
+ d->_rectImage = QImage(d->pen()->width()*2 + 1, d->pen()->width()*2 + 1, QImage::Format_ARGB32_Premultiplied);
+ d->_rectImage.fill(0);
+ QPainter p(&(d->_rectImage));
+ QPen pn(QColor(pen()->color()), pen()->width());
+ p.setRenderHint(QPainter::Antialiasing);
+ p.setPen(pn);
+ p.setBrush(d->_color);
+ p.drawRect(0, 0, d->_rectImage.width(), d->_rectImage.height());
+ }
+}
+#elif defined(QFX_RENDER_OPENGL)
+void QFxRect::generateRoundedRect()
+{
+ Q_D(QFxRect);
+ if (d->_rectTexture.isNull()) {
+ QImage roundRect(int(d->_radius*2 + 1), int(d->_radius*2 + 1), QImage::Format_ARGB32);
+ roundRect.fill(0);
+ QPainter p(&roundRect);
+ QPen pn(QColor(pen()->color()), pen()->width());
+ p.setRenderHint(QPainter::Antialiasing);
+ p.setPen(pn);
+ p.setBrush(d->_color);
+ p.drawRoundedRect(0, 0, roundRect.width(), roundRect.height(), d->_radius, d->_radius);
+ d->_rectTexture.setImage(roundRect);
+ }
+}
+
+void QFxRect::generateBorderedRect()
+{
+ Q_D(QFxRect);
+ if (d->_rectTexture.isNull()) {
+ QImage borderedRect(d->pen()->width()*2 + 1, d->pen()->width()*2 + 1, QImage::Format_ARGB32_Premultiplied);
+ borderedRect.fill(0);
+ QPainter p(&(borderedRect));
+ QPen pn(QColor(pen()->color()), pen()->width());
+ p.setRenderHint(QPainter::Antialiasing);
+ p.setPen(pn);
+ p.setBrush(d->_color);
+ p.drawRect(0, 0, borderedRect.width(), borderedRect.height());
+ d->_rectTexture.setImage(borderedRect);
+ }
+}
+#endif
+
+
+#if defined(QFX_RENDER_QPAINTER)
+void QFxRect::paintContents(QPainter &p)
+{
+ Q_D(QFxRect);
+ if (d->_radius > 0 || (d->_pen && d->_pen->isValid())
+ || d->_gradcolor.isValid())
+ drawRect(p);
+ /*
+ QLinearGradient grad(0, 0, 0, height());
+ grad.setColorAt(0, d->_color);
+ grad.setColorAt(1, d->_gradcolor);
+ p.setBrush(grad);
+ p.drawRect(0, 0, width(), height());
+ p.setBrush(QBrush());
+ */
+ else
+ p.fillRect(QRect(0, 0, width(), height()), d->getColor());
+}
+
+void QFxRect::drawRect(QPainter &p)
+{
+ Q_D(QFxRect);
+ if (d->_gradcolor.isValid() /*|| p.usingQt() */) {
+ // XXX This path is still slower than the image path
+ // Image path won't work for gradients though
+ p.save();
+ QPen pn(QColor(pen()->color()), pen()->width());
+ p.setRenderHint(QPainter::Antialiasing);
+ p.setPen(pn);
+ if (d->_gradcolor.isValid()){
+ QLinearGradient grad(0, 0, 0, height());
+ grad.setColorAt(0, d->_color);
+ grad.setColorAt(1, d->_gradcolor);
+ p.setBrush(grad);
+ }else{
+ p.setBrush(d->_color);
+ }
+ if (d->_radius)
+ p.drawRoundedRect(0, 0, width(), height(), d->_radius, d->_radius);
+ else
+ p.drawRect(0, 0, width(), height());
+ p.restore();
+ } else {
+ int offset = 0;
+ if (d->_radius > 0) {
+ generateRoundedRect();
+ //### implicit conversion to int
+ offset = d->_radius;
+ } else {
+ generateBorderedRect();
+ offset = d->pen()->width();
+ }
+
+ //basically same code as QFxImage uses to paint sci images
+ int xSide = offset * 2;
+ int ySide = offset * 2;
+
+ // Upper left
+ p.drawImage(QRect(0, 0, offset, offset), d->_rectImage, QRect(0, 0, offset, offset));
+
+ // Upper middle
+ if (d->_rectImage.width() - xSide)
+ p.drawImage(QRect(offset, 0, width() - xSide, offset), d->_rectImage,
+ QRect(offset, 0, d->_rectImage.width() - xSide, offset));
+ // Upper right
+ if (d->_rectImage.width() - offset) {
+ p.drawImage(QPoint(width()-offset, 0), d->_rectImage,
+ QRect(d->_rectImage.width()-offset, 0, offset, offset));
+ }
+ // Middle left
+ if (d->_rectImage.height() - ySide)
+ p.drawImage(QRect(0, offset, offset, height() - ySide), d->_rectImage,
+ QRect(0, offset, offset, d->_rectImage.height() - ySide));
+
+ // Middle
+ if (d->_rectImage.width() - xSide && d->_rectImage.height() - ySide)
+ p.drawImage(QRect(offset, offset, width() - xSide, height() - ySide), d->_rectImage,
+ QRect(offset, offset, d->_rectImage.width() - xSide, d->_rectImage.height() - ySide));
+ // Midlle right
+ if (d->_rectImage.height() - ySide)
+ p.drawImage(QRect(width()-offset, offset, offset, height() - ySide), d->_rectImage,
+ QRect(d->_rectImage.width()-offset, offset, offset, d->_rectImage.height() - ySide));
+ // Lower left
+ p.drawImage(QPoint(0, height() - offset), d->_rectImage, QRect(0, d->_rectImage.height() - offset, offset, offset));
+
+ // Lower Middle
+ if (d->_rectImage.width() - xSide)
+ p.drawImage(QRect(offset, height() - offset, width() - xSide, offset), d->_rectImage,
+ QRect(offset, d->_rectImage.height() - offset, d->_rectImage.width() - xSide, offset));
+ // Lower Right
+ if (d->_rectImage.width() - offset)
+ p.drawImage(QPoint(width()-offset, height() - offset), d->_rectImage,
+ QRect(d->_rectImage.width()-offset, d->_rectImage.height() - offset, offset, offset));
+ }
+}
+#endif
+
+#if defined(QFX_RENDER_OPENGL2)
+#include "glbasicshaders.h"
+
+void QFxRect::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxRect);
+ if (d->_radius == 0 && (!d->_pen || !d->_pen->isValid())) {
+ if (d->_gradcolor.isValid()) {
+ float widthV = width();
+ float heightV = height();
+
+ GLfloat vertices[] = { 0, heightV,
+ widthV, heightV,
+ 0, 0,
+ widthV, 0 };
+
+ float r = d->_color.redF();
+ float g = d->_color.greenF();
+ float b = d->_color.blueF();
+ float a = d->_color.alphaF() * p.activeOpacity;
+
+ float r2 = d->_gradcolor.redF();
+ float g2 = d->_gradcolor.greenF();
+ float b2 = d->_gradcolor.blueF();
+ float a2 = d->_gradcolor.alphaF() * p.activeOpacity;
+
+ GLfloat colors[] = { r2, g2, b2, a2,
+ r2, g2, b2, a2,
+ r, g, b, a,
+ r, g, b, a };
+
+ ColorShader *shader = basicShaders()->color();
+ shader->enable();
+ shader->setTransform(p.activeTransform);
+
+ shader->setAttributeArray(ColorShader::Vertices, vertices, 2);
+ shader->setAttributeArray(ColorShader::Colors, colors, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(ColorShader::Vertices);
+ shader->disableAttributeArray(ColorShader::Colors);
+ } else {
+ QGLShaderProgram *shader = p.useColorShader(d->getColor());
+
+ float widthV = width();
+ float heightV = height();
+
+ GLfloat vertices[] = { 0, heightV,
+ widthV, heightV,
+ 0, 0,
+ widthV, 0 };
+
+ shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(ConstantColorShader::Vertices);
+ }
+ } else {
+ qreal offset = 0;
+ if (d->_radius > 0) {
+ generateRoundedRect();
+ offset = d->_radius;
+ } else {
+ generateBorderedRect();
+ offset = d->pen()->width();
+ }
+
+ QGLShaderProgram *shader = p.useTextureShader();
+
+ float imgWidth = d->_rectTexture.width();
+ float imgHeight = d->_rectTexture.height();
+ if (!imgWidth || !imgHeight)
+ return;
+
+ float widthV = width();
+ float heightV = height();
+
+ float texleft = 0;
+ float texright = 1;
+ float textop = 1;
+ float texbottom = 0;
+ float imgleft = 0;
+ float imgright = widthV;
+ float imgtop = 0;
+ float imgbottom = heightV;
+
+ texleft = float(offset) / imgWidth;
+ imgleft = offset;
+ texright = 1. - float(offset) / imgWidth;
+ imgright = widthV - offset;
+ textop = 1. - float(offset) / imgHeight;
+ imgtop = offset;
+ texbottom = float(offset) / imgHeight;
+ imgbottom = heightV - offset;
+
+ //Bug 231768: Inappropriate interpolation was occuring on 3x3 textures
+ if (offset==1)
+ texleft=texright=textop=texbottom=0.5;
+
+ float vert1[] = { 0, 0,
+ 0, imgtop,
+ imgleft, 0,
+ imgleft, imgtop,
+ imgright, 0,
+ imgright, imgtop,
+ widthV, 0,
+ widthV, imgtop };
+ float tex1[] = { 0, 0,
+ 0, textop,
+ texleft, 0,
+ texleft, textop,
+ texright, 0,
+ texright, textop,
+ 1, 0,
+ 1, textop };
+ float vert2[] = { 0, imgtop,
+ 0, imgbottom,
+ imgleft, imgtop,
+ imgleft, imgbottom,
+ imgright, imgtop,
+ imgright, imgbottom,
+ widthV, imgtop,
+ widthV, imgbottom };
+ float tex2[] = { 0, textop,
+ 0, texbottom,
+ texleft, textop,
+ texleft, texbottom,
+ texright, textop,
+ texright, texbottom,
+ 1, textop,
+ 1, texbottom };
+ float vert3[] = { 0, imgbottom,
+ 0, heightV,
+ imgleft, imgbottom,
+ imgleft, heightV,
+ imgright, imgbottom,
+ imgright, heightV,
+ widthV, imgbottom,
+ widthV, heightV };
+ float tex3[] = { 0, texbottom,
+ 0, 0,
+ texleft, texbottom,
+ texleft, 0,
+ texright, texbottom,
+ texright, 0,
+ 1, texbottom,
+ 1, 0 };
+
+ glBindTexture(GL_TEXTURE_2D, d->_rectTexture.texture());
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert2, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, tex2, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+ shader->setAttributeArray(SingleTextureShader::Vertices, vert3, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, tex3, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+ }
+}
+#elif defined(QFX_RENDER_OPENGL1)
+void QFxRect::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxRect);
+
+ float widthV = width();
+ float heightV = height();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(p.activeTransform.data());
+
+ if (d->_radius == 0 && (!d->_pen || !d->_pen->isValid())) {
+ GLfloat vertices[] = { 0, heightV,
+ widthV, heightV,
+ 0, 0,
+ widthV, 0 };
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2,GL_FLOAT,0,vertices);
+
+ QColor c;
+ if (d->_gradcolor.isValid())
+ c = d->_color;
+ else
+ c = d->getColor();
+ float r = c.redF();
+ float g = c.greenF();
+ float b = c.blueF();
+ float a = c.alphaF() * p.activeOpacity;
+
+ float r2 = r; float g2 = g; float b2 = b; float a2 = a;
+
+ if (d->_gradcolor.isValid()) {
+ r2 = d->_gradcolor.redF();
+ g2 = d->_gradcolor.greenF();
+ b2 = d->_gradcolor.blueF();
+ a2 = d->_gradcolor.alphaF() * p.activeOpacity;
+ }
+
+ GLfloat colors[] = { r2, g2, b2, a2,
+ r2, g2, b2, a2,
+ r, g, b, a,
+ r, g, b, a };
+
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(4,GL_FLOAT,0,colors);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ } else {
+ qreal offset = 0;
+ if (d->_radius > 0) {
+ generateRoundedRect();
+ offset = d->_radius;
+ } else {
+ generateBorderedRect();
+ offset = d->pen()->width();
+ }
+
+ if (p.activeOpacity == 1.) {
+ GLint i = GL_REPLACE;
+ glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i);
+ } else {
+ GLint i = GL_MODULATE;
+ glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i);
+ glColor4f(1, 1, 1, p.activeOpacity);
+ }
+
+ float imgWidth = d->_rectTexture.width();
+ float imgHeight = d->_rectTexture.height();
+ if (!imgWidth || !imgHeight)
+ return;
+
+ float widthV = width();
+ float heightV = height();
+
+ float texleft = 0;
+ float texright = 1;
+ float textop = 1;
+ float texbottom = 0;
+ float imgleft = 0;
+ float imgright = widthV;
+ float imgtop = 0;
+ float imgbottom = heightV;
+
+ texleft = float(offset) / imgWidth;
+ imgleft = offset;
+ texright = 1. - float(offset) / imgWidth;
+ imgright = widthV - offset;
+ textop = 1. - float(offset) / imgHeight;
+ imgtop = offset;
+ texbottom = float(offset) / imgHeight;
+ imgbottom = heightV - offset;
+
+ float vert1[] = { 0, 0,
+ 0, imgtop,
+ imgleft, 0,
+ imgleft, imgtop,
+ imgright, 0,
+ imgright, imgtop,
+ widthV, 0,
+ widthV, imgtop };
+ float tex1[] = { 0, 1,
+ 0, textop,
+ texleft, 1,
+ texleft, textop,
+ texright, 1,
+ texright, textop,
+ 1, 1,
+ 1, textop };
+ float vert2[] = { 0, imgtop,
+ 0, imgbottom,
+ imgleft, imgtop,
+ imgleft, imgbottom,
+ imgright, imgtop,
+ imgright, imgbottom,
+ widthV, imgtop,
+ widthV, imgbottom };
+ float tex2[] = { 0, textop,
+ 0, texbottom,
+ texleft, textop,
+ texleft, texbottom,
+ texright, textop,
+ texright, texbottom,
+ 1, textop,
+ 1, texbottom };
+ float vert3[] = { 0, imgbottom,
+ 0, heightV,
+ imgleft, imgbottom,
+ imgleft, heightV,
+ imgright, imgbottom,
+ imgright, heightV,
+ widthV, imgbottom,
+ widthV, heightV };
+ float tex3[] = { 0, texbottom,
+ 0, 0,
+ texleft, texbottom,
+ texleft, 0,
+ texright, texbottom,
+ texright, 0,
+ 1, texbottom,
+ 1, 0 };
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, d->_rectTexture.texture());
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, 0, vert1);
+ glTexCoordPointer(2, GL_FLOAT, 0, tex1);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+
+ glVertexPointer(2, GL_FLOAT, 0, vert2);
+ glTexCoordPointer(2, GL_FLOAT, 0, tex2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+
+ glVertexPointer(2, GL_FLOAT, 0, vert3);
+ glTexCoordPointer(2, GL_FLOAT, 0, tex3);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D);
+ }
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxrect.h b/src/declarative/fx/qfxrect.h
new file mode 100644
index 0000000..42e7b2f
--- /dev/null
+++ b/src/declarative/fx/qfxrect.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXRECT_H
+#define QFXRECT_H
+
+#include <qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QFxPen : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int width READ width WRITE setWidth)
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+public:
+ QFxPen(QObject *parent=0)
+ : QObject(parent), _width(1), _color("#000000"), _valid(false)
+ {}
+
+ int width() const { return _width; }
+ void setWidth(int w) { _width = w; emit updated(); _valid = (_width < 1) ? false : true; }
+
+ QColor color() const { return _color; }
+ void setColor(const QColor &c);
+
+ bool isValid() { return _valid; };
+
+Q_SIGNALS:
+ void updated();
+
+private:
+ int _width;
+ QColor _color;
+ bool _valid;
+};
+QML_DECLARE_TYPE(QFxPen);
+
+class QFxRectPrivate;
+class Q_DECLARATIVE_EXPORT QFxRect : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+ Q_PROPERTY(QColor tintColor READ tintColor WRITE setTintColor)
+ Q_PROPERTY(QColor gradientColor READ gradientColor WRITE setGradientColor)
+ Q_PROPERTY(QFxPen * pen READ pen)
+ Q_PROPERTY(qreal radius READ radius WRITE setRadius)
+public:
+ QFxRect(QFxItem *parent=0);
+
+ QColor color() const;
+ void setColor(const QColor &);
+
+ QColor tintColor() const;
+ void setTintColor(const QColor &);
+
+ QColor gradientColor() const;
+ void setGradientColor(const QColor &);
+
+ QFxPen *pen();
+
+ qreal radius() const;
+ void setRadius(qreal radius);
+
+ virtual void dump(int depth);
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &painter);
+#endif
+
+#if defined(QFX_RENDER_OPENGL)
+ void paintGLContents(GLPainter &);
+#endif
+
+private Q_SLOTS:
+ void doUpdate();
+
+private:
+ void generateRoundedRect();
+ void generateBorderedRect();
+#if defined(QFX_RENDER_QPAINTER)
+ void drawRect(QPainter &painter);
+#endif
+protected:
+ QFxRect(QFxRectPrivate &dd, QFxItem *parent);
+
+private:
+ Q_DISABLE_COPY(QFxRect)
+ Q_DECLARE_PRIVATE(QFxRect)
+};
+QML_DECLARE_TYPE(QFxRect);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXRECT_H
diff --git a/src/declarative/fx/qfxrect_p.h b/src/declarative/fx/qfxrect_p.h
new file mode 100644
index 0000000..2fd555f
--- /dev/null
+++ b/src/declarative/fx/qfxrect_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXRECT_P_H
+#define QFXRECT_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 "qfxitem_p.h"
+
+#if defined(QFX_RENDER_OPENGL)
+#include "gltexture.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QFxRectPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxRect)
+
+public:
+ QFxRectPrivate()
+ : _pen(0), _radius(0)
+ {
+ }
+
+ ~QFxRectPrivate()
+ {
+ delete _pen;
+ }
+
+ void init()
+ {
+ }
+
+#if defined(QFX_RENDER_OPENGL)
+ GLTexture _rectTexture;
+#endif
+ QColor getColor();
+ QColor _color;
+ QColor _gradcolor;
+ QColor _tintColor;
+ QFxPen *pen() {
+ if (!_pen) {
+ Q_Q(QFxRect);
+ _pen = new QFxPen;
+ QObject::connect(_pen, SIGNAL(updated()), q, SLOT(doUpdate()));
+ }
+ return _pen;
+ }
+ QFxPen *_pen;
+ qreal _radius;
+#if defined(QFX_RENDER_QPAINTER)
+ QSimpleCanvasConfig::Image _rectImage;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QFXRECT_P_H
diff --git a/src/declarative/fx/qfxreflectionfilter.cpp b/src/declarative/fx/qfxreflectionfilter.cpp
new file mode 100644
index 0000000..0bc01a7
--- /dev/null
+++ b/src/declarative/fx/qfxreflectionfilter.cpp
@@ -0,0 +1,352 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxreflectionfilter.h"
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glsave.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#include <glbasicshaders.h>
+#include <gltexture.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+class QFxReflectionFilterPrivate
+{
+public:
+ QFxReflectionFilterPrivate()
+ : alpha(1), height(-1), offset(0), scale(1)
+ {
+ }
+ qreal alpha;
+ int height;
+ int offset;
+ qreal scale;
+};
+
+/*!
+ \qmlclass Reflection
+ \inherits Filter
+ \brief The Reflection filter reflects an item and its contents.
+
+ Here is an example of various Reflections applied to an image.
+
+ \qml
+HorizontalLayout {
+ Image {
+ source: "icon.png"
+ filter: Reflection { }
+ }
+ Image {
+ source: "icon.png"
+ filter: Reflection { offset: 1 }
+ }
+ Image {
+ source: "icon.png"
+ filter: Reflection { offset: 1; alpha: 0.5 }
+ }
+ Image {
+ source: "icon.png"
+ filter: Reflection { offset: 1; alpha: 0.5; height: 50 }
+ }
+ Image {
+ source: "icon.png"
+ filter: Reflection { offset: 1; alpha: 0.5; height: 50; scale: 0.5 }
+ }
+}
+ \endqml
+
+ \image reflection_example.png
+
+ Reflection is only supported when Qt Declarative is compiled for OpenGL ES 2.0.
+ Otherwise the Reflection filter has no effect.
+*/
+
+/*!
+ \internal
+ \class QFxReflectionFilter
+ \ingroup group_effects
+ \brief The QFxReflectionFilter class allows you to add a reflection to an item.
+*/
+QFxReflectionFilter::QFxReflectionFilter(QObject *parent)
+: QSimpleCanvasFilter(parent), d(new QFxReflectionFilterPrivate)
+{
+}
+
+QFxReflectionFilter::~QFxReflectionFilter()
+{
+ delete d; d = 0;
+}
+
+/*!
+ \property QFxReflectionFilter::alpha
+ \brief the starting opacity of the reflection.
+
+ The starting opacity is the opacity closest to the item. The opacity will fade
+ from this value to zero over the height of the reflection.
+*/
+qreal QFxReflectionFilter::alpha() const
+{
+ return d->alpha;
+}
+
+void QFxReflectionFilter::setAlpha(qreal a)
+{
+ if (d->alpha == a) return;
+ d->alpha = a;
+ emit alphaChanged(a);
+ update();
+}
+
+/*!
+ \qmlproperty int Reflection::height
+
+ The height property controls how much of the item, in pixels, to reflect.
+ If it is set to the default value of -1, the whole item is reflected. If
+ it is set to 50, the bottom 50 pixels of the item are reflected. Data
+ binding could be used to reflect a percentage of the item.
+
+ \qml
+Image {
+ id: myImage
+ source: "album.png"
+ filter: Reflection {
+ height: myImage.height * 0.5
+ }
+}
+ \endqml
+ */
+/*!
+ \qmlproperty int Reflection::offset
+
+ The offset controls how far from the base of the item, in pixels, the
+ start of the reflection is placed. This can be used to create a nice
+ sliver of space between the item and its reflection or for more advanced
+ effects.
+
+ The default offset is 0 pixels.
+*/
+
+/*!
+ \qmlproperty real Reflection::alpha
+
+ The alpha value controls the starting opacity of the reflected item. If
+ set to the default value of 1, the reflected item starts completely opaque
+ and gradually fades to completely transparent. If set to less than one, the
+ reflection starts out partially transparent as though the item was sitting
+ on a visually less reflective surface.
+
+ Valid values are from 0 (which would be silly, but is allowed) to 1.
+*/
+/*!
+ \qmlproperty real Reflection::scale
+
+ When set to the default value of 1, the reflection is a 1:1 reflection of
+ the item. That is, each horizontal pixel in the item corresponds to one
+ horizontal pixel in the reflection.
+
+ When set a value other than 1, the reflection is scaled acordingly - less
+ than 1 scales it down and greater than 1 scales it up. The scale is applied
+ after the height parameter and does not effect the reflection offset.
+*/
+
+/*!
+ \property QFxReflectionFilter::height
+ \brief the height of the reflection, in pixels.
+*/
+int QFxReflectionFilter::height() const
+{
+ return d->height;
+}
+
+void QFxReflectionFilter::setHeight(int h)
+{
+ if (d->height == h) return;
+ d->height = h;
+ emit heightChanged(h);
+ update();
+}
+
+/*!
+ \property QFxReflectionFilter::offset
+ \brief the distance of the reflection from the item, in pixels.
+*/
+int QFxReflectionFilter::offset()
+{
+ return d->offset;
+}
+
+void QFxReflectionFilter::setOffset(int o)
+{
+ if (d->offset == o) return;
+ d->offset = o;
+ emit offsetChanged(o);
+ update();
+}
+
+/*!
+ \property QFxReflectionFilter::scale
+ \brief the scale of the reflection relative to the item.
+*/
+qreal QFxReflectionFilter::scale() const
+{
+ return d->scale;
+}
+
+void QFxReflectionFilter::setScale(qreal s)
+{
+ if (d->scale == s) return;
+ d->scale = s;
+ emit scaleChanged(s);
+ update();
+}
+
+static inline float min(float a, float b)
+{
+ return (a < b)?a:b;
+}
+
+void QFxReflectionFilter::filterGL(QSimpleCanvasItem::GLPainter &p)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ QSimpleCanvasItem *item = this->item();
+
+ QRect r = item->itemBoundingRect();
+ if (r.isEmpty())
+ return;
+ float width = r.width();
+ float height = r.height();
+
+ float refHeight = height;
+ if (d->height > 0)
+ refHeight = min(height, d->height);
+
+ QSimpleCanvas::Matrix simpMat;
+ QSimpleCanvasItem *simpItem = 0;
+ if (isSimpleItem(&simpItem, &simpMat) &&
+ simpItem->glSimpleItemData(0, 0, 0, 0)) {
+
+ GLfloat vertices[8];
+ GLfloat texVertices[8];
+ GLTexture *texture = 0;
+
+ simpItem->glSimpleItemData(vertices, texVertices, &texture, 8);
+
+ GLfloat opacity[4];
+
+ float invRefHeight = 1. / refHeight;
+ for (int ii = 0; ii < 4; ++ii) {
+ float vertex = vertices[ii * 2 + 1];
+ float o = (1. - (height - vertex) * invRefHeight);
+ opacity[ii] = o * d->alpha * p.activeOpacity;
+ }
+
+ QSimpleCanvas::Matrix trans = p.activeTransform;
+ trans.rotate(180, 1, 0, 0);
+ trans.translate(0, -r.height() - d->offset);
+ if (d->scale != 1)
+ trans.scale(1, d->scale, 1);
+ trans.translate(0, -r.height());
+ trans *= simpMat;
+
+ glBindTexture(GL_TEXTURE_2D, texture->texture());
+
+ SingleTextureVertexOpacityShader *shader =
+ item->basicShaders()->singleTextureVertexOpacity();
+ shader->enable();
+ shader->setTransform(trans);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::TextureCoords, texVertices, 2);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::OpacityCoords, opacity, 1);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::Vertices);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::TextureCoords);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::OpacityCoords);
+
+ } else {
+ QGLFramebufferObject *fbo = renderToFBO();
+
+ float texWidth = width / float(fbo->width());
+ float texHeight = refHeight / float(fbo->height());
+
+ GLfloat invVertices[] = { width, height + d->scale * refHeight + d->offset,
+ 0, height + d->scale * refHeight + d->offset,
+ width, height + d->offset,
+ 0, height + d->offset };
+ GLfloat invTexVertices[] = { texWidth, texHeight,
+ 0, texHeight,
+ texWidth, 0,
+ 0, 0 };
+ GLfloat invOpacity[] = { 0, 0, d->alpha * p.activeOpacity, d->alpha * p.activeOpacity};
+
+ glBindTexture(GL_TEXTURE_2D, fbo->texture());
+
+ SingleTextureVertexOpacityShader *shader =
+ item->basicShaders()->singleTextureVertexOpacity();
+ shader->enable();
+ shader->setTransform(p.activeTransform);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::Vertices, invVertices, 2);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::TextureCoords, invTexVertices, 2);
+ shader->setAttributeArray(SingleTextureVertexOpacityShader::OpacityCoords, invOpacity, 1);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::Vertices);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::TextureCoords);
+ shader->disableAttributeArray(SingleTextureVertexOpacityShader::OpacityCoords);
+
+ releaseFBO(fbo);
+ }
+
+ renderToScreen();
+
+#else
+ Q_UNUSED(p);
+#endif
+}
+
+QRectF QFxReflectionFilter::itemBoundingRect(const QRectF &r) const
+{
+ QRectF rv = r;
+ rv |= r.translated(0, r.height() + d->offset);
+ return rv;
+}
+
+QML_DEFINE_TYPE(QFxReflectionFilter,Reflection);
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxreflectionfilter.h b/src/declarative/fx/qfxreflectionfilter.h
new file mode 100644
index 0000000..b0cc7b2
--- /dev/null
+++ b/src/declarative/fx/qfxreflectionfilter.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXREFLECTIONFILTER_H
+#define QFXREFLECTIONFILTER_H
+
+#include <qsimplecanvasfilter.h>
+#include <qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxReflectionFilterPrivate;
+class Q_DECLARATIVE_EXPORT QFxReflectionFilter : public QSimpleCanvasFilter
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal alpha READ alpha WRITE setAlpha NOTIFY alphaChanged)
+ Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged)
+ Q_PROPERTY(int offset READ offset WRITE setOffset NOTIFY offsetChanged)
+ Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
+public:
+ QFxReflectionFilter(QObject *parent=0);
+ virtual ~QFxReflectionFilter();
+
+ qreal alpha() const;
+ void setAlpha(qreal);
+ int height() const;
+ void setHeight(int);
+ int offset();
+ void setOffset(int);
+ qreal scale() const;
+ void setScale(qreal);
+
+Q_SIGNALS:
+ void alphaChanged(qreal);
+ void heightChanged(int);
+ void offsetChanged(int);
+ void scaleChanged(qreal);
+
+protected:
+ virtual void filterGL(QSimpleCanvasItem::GLPainter &p);
+ virtual QRectF itemBoundingRect(const QRectF &r) const;
+
+private:
+ Q_DISABLE_COPY(QFxReflectionFilter)
+ QFxReflectionFilterPrivate *d;
+};
+QML_DECLARE_TYPE(QFxReflectionFilter);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXREFLECTIONFILTER_H
diff --git a/src/declarative/fx/qfxrepeater.cpp b/src/declarative/fx/qfxrepeater.cpp
new file mode 100644
index 0000000..23b4e01
--- /dev/null
+++ b/src/declarative/fx/qfxrepeater.cpp
@@ -0,0 +1,356 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxrepeater.h"
+#include "qfxrepeater_p.h"
+#include "qmllistaccessor.h"
+#include <qlistmodelinterface.h>
+
+
+QT_BEGIN_NAMESPACE
+QFxRepeaterPrivate::QFxRepeaterPrivate()
+: component(0)
+{
+}
+
+QFxRepeaterPrivate::~QFxRepeaterPrivate()
+{
+}
+
+QFxItem *QFxRepeaterPrivate::addItem(QmlContext *ctxt, QFxItem *lastItem)
+{
+ Q_Q(QFxRepeater);
+ QObject *nobj = component->create(ctxt);
+ QFxItem *item = qobject_cast<QFxItem *>(nobj);
+ if (item) {
+ item->setParent(q->itemParent());
+ item->stackUnder(lastItem);
+ deletables << nobj;
+ } else {
+ delete nobj;
+ }
+
+ return item;
+}
+
+QML_DEFINE_TYPE(QFxRepeater,Repeater);
+
+/*!
+ \qmlclass Repeater
+ \inherits Item
+
+ \brief The Repeater item allows you to repeat a component based on a data source.
+
+ The Repeater item is used when you want to create a large number of
+ similar items. For each entry in the data source, an item is instantiated
+ in a context seeded with data from the data source. If the repeater will
+ be instantiating a large number of instances, it may be more efficient to
+ use one of Qt Declarative's \l {xmlViews}{view items}.
+
+ The data source may be either an object list, a string list or a Qt model.
+ In each case, the data element and the index is exposed to each instantiated
+ component. The index is always exposed as an accessible \c index property.
+ In the case of an object or string list, the data element (of type string
+ or object) is available as the \c modelData property. In the case of a Qt model,
+ all roles are available as named properties just like in the view classes.
+
+ Items instantiated by the Repeater are inserted, in order, as
+ children of the Repeater's parent. The insertion starts immediately after
+ the repeater's position in its parent stacking list. This is to allow
+ you to use a Repeater inside a layout. The following QML example shows how
+ the instantiated items would visually appear stacked between the red and
+ blue rectangles.
+
+ \snippet doc/src/snippets/declarative/repeater.qml 0
+
+ \image repeater.png
+
+ The repeater instance continues to own all items it instantiates, even
+ if they are otherwise manipulated. It is illegal to manually remove an item
+ created by the Repeater.
+ */
+
+/*!
+ \internal
+ \class QFxRepeater
+ \ingroup group_utility
+ \qmlclass Repeater
+
+ \brief The QFxRepeater class allows you to repeat a component based on a
+ data source.
+
+ The QFxRepeater class is used when you want to create a large number of
+ similar items. For each entry in the data source, an item is instantiated
+ in a context seeded with data from the data source.
+
+ The data source may be either an object list, a string list or a Qt model.
+ In each case, the data element and the index is exposed to each instantiated
+ component. The index is always exposed as an accessible \c index property.
+ In the case of an object or string list, the data element (of type string
+ or object) is available as the \c modelData property. In the case of a Qt model,
+ all roles are available as named properties just like in the view classes.
+
+ As a special case the data source can also be merely a number. In this case it will
+ create that many instances of the component. They will also be assigned an index
+ based on the order they are created.
+
+ Items instantiated by the QFxRepeater class are inserted, in order, as
+ children of the repeater's parent. The insertion starts immediately after
+ the repeater's position in its parent stacking list. This is to allow
+ you to use a repeater inside a layout. The following QML example shows how
+ the instantiated items would visually appear stacked between the red and
+ blue rectangles.
+
+ \snippet doc/src/snippets/declarative/repeater.qml 0
+
+ The QFxRepeater instance continues to own all items it instantiates, even
+ if they are otherwise manipulated. It is illegal to manually delete an item
+ created by the repeater. On destruction, the repeater will clean up any
+ items it has instantiated.
+
+
+ XXX Repeater is very conservative in how it instatiates/deletes items. Also
+ new model entries will not be created and old ones will not be removed.
+ */
+
+/*!
+ Create a new QFxRepeater instance.
+ */
+QFxRepeater::QFxRepeater(QFxItem *parent)
+ : QFxItem(*(new QFxRepeaterPrivate), parent)
+{
+}
+
+/*!
+ \internal
+ */
+QFxRepeater::QFxRepeater(QFxRepeaterPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+}
+
+/*!
+ Destroy the repeater instance. All items it instantiated are also
+ destroyed.
+ */
+QFxRepeater::~QFxRepeater()
+{
+}
+
+/*!
+ \qmlproperty any Repeater::dataSource
+
+ The Repeater's data source.
+
+ The data source may be either an object list, a string list or a Qt model.
+ In each case, the data element and the index is exposed to each instantiated
+ component. The index is always exposed as an accessible \c index property.
+ In the case of an object or string list, the data element (of type string
+ or object) is available as the \c modelData property. In the case of a Qt model,
+ all roles are available as named properties just like in the view classes.
+
+ As a special case the data source can also be merely a number. In this case it will
+ create that many instances of the component. They will also be assigned an index
+ based on the order they are created.
+*/
+
+/*!
+ \property QFxRepeater::dataSource
+ \brief The source of data for the repeater.
+ */
+QVariant QFxRepeater::dataSource() const
+{
+ return QVariant();
+}
+
+void QFxRepeater::setDataSource(const QVariant &v)
+{
+ Q_D(QFxRepeater);
+ d->dataSource = v;
+ regenerate();
+}
+
+/*!
+ \qmlproperty Component Repeater::component
+ \default
+
+ The component to repeat.
+ */
+/*!
+ \property QFxRepeater::component
+ \brief The component to repeat.
+ */
+QmlComponent *QFxRepeater::component() const
+{
+ Q_D(const QFxRepeater);
+ return d->component;
+}
+
+void QFxRepeater::setComponent(QmlComponent *_c)
+{
+ Q_D(QFxRepeater);
+ d->component = _c;
+ regenerate();
+}
+
+/*!
+ \internal
+ */
+void QFxRepeater::componentComplete()
+{
+ QFxItem::componentComplete();
+ regenerate();
+}
+
+/*!
+ \internal
+ */
+void QFxRepeater::parentChanged(QSimpleCanvasItem *o, QSimpleCanvasItem *n)
+{
+ QFxItem::parentChanged(o, n);
+ regenerate();
+}
+
+/*!
+ \internal
+ */
+void QFxRepeater::regenerate()
+{
+ Q_D(QFxRepeater);
+
+ qDeleteAll(d->deletables);
+ d->deletables.clear();
+ if (!d->component || !itemParent() || !isComponentComplete())
+ return;
+
+ QFxItem *lastItem = this;
+
+ if (d->dataSource.type() == QVariant::StringList) {
+ QStringList sl = qvariant_cast<QStringList>(d->dataSource);
+
+ for (int ii = 0; ii < sl.size(); ++ii) {
+ QmlContext *ctxt = new QmlContext(qmlContext(this), this);
+ d->deletables << ctxt;
+
+ ctxt->setContextProperty(QLatin1String("index"), ii);
+ ctxt->setContextProperty(QLatin1String("modelData"), sl.at(ii));
+
+ if (QFxItem *item = d->addItem(ctxt, lastItem))
+ lastItem = item;
+ }
+ } else if (QmlMetaType::isList(d->dataSource)) {
+ int cnt = QmlMetaType::listCount(d->dataSource);
+ if (cnt <= 0)
+ return;
+
+ for (int ii = 0; ii < cnt; ++ii) {
+ QVariant v = QmlMetaType::listAt(d->dataSource, ii);
+ QObject *o = QmlMetaType::toQObject(v);
+
+ QmlContext *ctxt = new QmlContext(qmlContext(this), this);
+ d->deletables << ctxt;
+
+ ctxt->setContextProperty(QLatin1String("index"), ii);
+ ctxt->setContextProperty(QLatin1String("modelData"), o);
+
+ if (QFxItem *item = d->addItem(ctxt, lastItem))
+ lastItem = item;
+ }
+ } else if (QListModelInterface *model = qobject_cast<QListModelInterface*>(d->dataSource.value<QObject*>())) {
+ int cnt = model->count();
+ if (cnt <= 0)
+ return;
+
+ for (int ii = 0; ii < cnt; ++ii) {
+ QmlContext *ctxt = new QmlContext(qmlContext(this), this);
+ d->deletables << ctxt;
+
+ ctxt->setContextProperty(QLatin1String("index"), ii);
+
+ QList<int> roles = model->roles();
+ QHash<int,QVariant> data = model->data(ii,roles);
+ for (int j = 0; j < roles.size(); ++j) {
+ ctxt->setContextProperty(model->toString(roles.at(j)), data.value(roles.at(j)));
+ }
+
+ //for compatability with other lists, assign data if there is only a single role
+ if (roles.size() == 1)
+ ctxt->setContextProperty(QLatin1String("modelData"), data.value(roles.at(0)));
+
+ if (QFxItem *item = d->addItem(ctxt, lastItem))
+ lastItem = item;
+ }
+ } else if (QObject *object = d->dataSource.value<QObject*>()) {
+ // A single object (i.e. list of size 1).
+ // Properties are the roles (excluding objectName).
+ QmlContext *ctxt = new QmlContext(qmlContext(this), this);
+ d->deletables << ctxt;
+
+ ctxt->setContextProperty(QLatin1String("index"), QVariant(0));
+ for (int ii = 1; ii < object->metaObject()->propertyCount(); ++ii) {
+ const QMetaProperty &prop = object->metaObject()->property(ii);
+ ctxt->setContextProperty(QLatin1String(prop.name()), prop.read(object));
+ }
+
+ //for compatability with other lists, assign data if there is only a single role (excluding objectName)
+ if (object->metaObject()->propertyCount() == 2) {
+ const QMetaProperty &prop = object->metaObject()->property(1);
+ ctxt->setContextProperty(QLatin1String("modelData"), prop.read(object));
+ }
+
+ d->addItem(ctxt, lastItem);
+
+ } else if (d->dataSource.canConvert(QVariant::Int)){
+
+ int count = qvariant_cast<int>(d->dataSource);
+
+ for (int ii = 0; ii < count; ++ii) {
+ QmlContext *ctxt = new QmlContext(qmlContext(this), this);
+ d->deletables << ctxt;
+
+ ctxt->setContextProperty(QLatin1String("index"), ii);
+
+ if (QFxItem *item = d->addItem(ctxt, lastItem))
+ lastItem = item;
+ }
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxrepeater.h b/src/declarative/fx/qfxrepeater.h
new file mode 100644
index 0000000..8efd281
--- /dev/null
+++ b/src/declarative/fx/qfxrepeater.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXREPEATER_H
+#define QFXREPEATER_H
+
+#include <qfxitem.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxRepeaterPrivate;
+class Q_DECLARATIVE_EXPORT QFxRepeater : public QFxItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant dataSource READ dataSource WRITE setDataSource)
+ Q_PROPERTY(QmlComponent *component READ component WRITE setComponent)
+ Q_CLASSINFO("DefaultProperty", "component")
+public:
+ QFxRepeater(QFxItem *parent=0);
+ virtual ~QFxRepeater();
+
+ QVariant dataSource() const;
+ void setDataSource(const QVariant &);
+
+ QmlComponent *component() const;
+ void setComponent(QmlComponent *);
+
+private:
+ void regenerate();
+
+protected:
+ virtual void componentComplete();
+ virtual void parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *);
+ QFxRepeater(QFxRepeaterPrivate &dd, QFxItem *parent);
+
+private:
+ Q_DISABLE_COPY(QFxRepeater)
+ Q_DECLARE_PRIVATE(QFxRepeater)
+};
+QML_DECLARE_TYPE(QFxRepeater);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // _QFXREPEATER_H_
diff --git a/src/declarative/fx/qfxrepeater_p.h b/src/declarative/fx/qfxrepeater_p.h
new file mode 100644
index 0000000..ba69658
--- /dev/null
+++ b/src/declarative/fx/qfxrepeater_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXREPEATER_P_H
+#define QFXREPEATER_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 "qfxitem_p.h"
+#include "qfxrepeater.h"
+#include <QPointer>
+
+
+QT_BEGIN_NAMESPACE
+
+class QmlContext;
+class QFxRepeaterPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxRepeater)
+
+public:
+ QFxRepeaterPrivate();
+ ~QFxRepeaterPrivate();
+
+ QFxItem *addItem(QmlContext *ctxt, QFxItem *lastItem);
+
+ QVariant dataSource;
+ QmlComponent *component;
+
+ QList<QPointer<QObject> > deletables;
+};
+
+QT_END_NAMESPACE
+#endif // QFXREPEATER_P_H
diff --git a/src/declarative/fx/qfxscalegrid.cpp b/src/declarative/fx/qfxscalegrid.cpp
new file mode 100644
index 0000000..325f7d9
--- /dev/null
+++ b/src/declarative/fx/qfxscalegrid.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QBuffer>
+#include <qml.h>
+#include "qfxscalegrid.h"
+
+
+QT_BEGIN_NAMESPACE
+/*!
+ \internal
+ \class QFxScaleGrid
+ \brief The QFxScaleGrid class allows you to specify a 3x3 grid to use in scaling an image.
+
+ A scale grid uses 4 grid lines (2 horizontal and 2 vertical) to break an image into 9 sections, as shown below:
+ \image scalegrid.png
+
+ When the image is scaled:
+ \list
+ \i the corners (sections 1, 3, 7, and 9) are not scaled at all
+ \i the middle (section 5) is scaled both horizontally and vertically
+ \i sections 2 and 8 are scaled horizontally
+ \i sections 4 and 6 are scaled vertically
+ \endlist
+
+ A common way of specifying a scale grid is to create an sci file. An sci file uses a simple
+ text-based format that specifies each grid line, as well as the associated image file. An example of an sci file's contents:
+ \code
+ gridLeft: 10
+ gridTop: 10
+ gridBottom: 10
+ gridRight: 10
+ imageFile: picture.png
+ \endcode
+*/
+QML_DEFINE_NOCREATE_TYPE(QFxScaleGrid);
+
+QFxScaleGrid::QFxScaleGrid() : QObject(), _left(0), _top(0), _right(0), _bottom(0)
+{
+}
+
+QFxScaleGrid::~QFxScaleGrid()
+{
+}
+
+bool QFxScaleGrid::isNull() const
+{
+ return !_left && !_top && !_right && !_bottom;
+}
+
+/*!
+ \property QFxScaleGrid::left
+ \brief the position of the left grid line as an offset from the left side of the image.
+*/
+void QFxScaleGrid::setLeft(int pos)
+{
+ _left = pos;
+}
+
+/*!
+ \property QFxScaleGrid::top
+ \brief the position of the top grid line as an offset from the top of the image.
+*/
+void QFxScaleGrid::setTop(int pos)
+{
+ _top = pos;
+}
+
+/*!
+ \property QFxScaleGrid::right
+ \brief the position of the right grid line as an offset from the right side of the image.
+*/
+void QFxScaleGrid::setRight(int pos)
+{
+ _right = pos;
+}
+
+/*!
+ \property QFxScaleGrid::bottom
+ \brief the position of the bottom grid line as an offset from the bottom of the image.
+*/
+void QFxScaleGrid::setBottom(int pos)
+{
+ _bottom = pos;
+}
+
+QFxGridScaledImage::QFxGridScaledImage()
+: _l(-1), _r(-1), _t(-1), _b(-1)
+{
+}
+
+QFxGridScaledImage::QFxGridScaledImage(const QFxGridScaledImage &o)
+: _l(o._l), _r(o._r), _t(o._t), _b(o._b), _pix(o._pix)
+{
+}
+
+QFxGridScaledImage &QFxGridScaledImage::operator=(const QFxGridScaledImage &o)
+{
+ _l = o._l;
+ _r = o._r;
+ _t = o._t;
+ _b = o._b;
+ _pix = o._pix;
+ return *this;
+}
+
+QFxGridScaledImage::QFxGridScaledImage(QIODevice *data)
+: _l(-1), _r(-1), _t(-1), _b(-1)
+{
+ int l = -1;
+ int r = -1;
+ int t = -1;
+ int b = -1;
+ QString imgFile;
+
+ while(!data->atEnd()) {
+ QString line = QString::fromUtf8(data->readLine().trimmed());
+ if (line.isEmpty() || line.startsWith(QLatin1String("#")))
+ continue;
+
+ QStringList list = line.split(QLatin1Char(':'));
+ if (list.count() != 2)
+ return;
+
+ list[0] = list[0].trimmed();
+ list[1] = list[1].trimmed();
+
+ if (list[0] == QLatin1String("gridLeft"))
+ l = list[1].toInt();
+ else if (list[0] == QLatin1String("gridRight"))
+ r = list[1].toInt();
+ else if (list[0] == QLatin1String("gridTop"))
+ t = list[1].toInt();
+ else if (list[0] == QLatin1String("gridBottom"))
+ b = list[1].toInt();
+ else if (list[0] == QLatin1String("imageFile"))
+ imgFile = list[1];
+ }
+
+ if (l < 0 || r < 0 || t < 0 || b < 0 || imgFile.isEmpty())
+ return;
+
+ _l = l; _r = r; _t = t; _b = b;
+
+ _pix = imgFile;
+}
+
+bool QFxGridScaledImage::isValid() const
+{
+ return _l >= 0;
+}
+
+int QFxGridScaledImage::gridLeft() const
+{
+ return _l;
+}
+
+int QFxGridScaledImage::gridRight() const
+{
+ return _r;
+}
+
+int QFxGridScaledImage::gridTop() const
+{
+ return _t;
+}
+
+int QFxGridScaledImage::gridBottom() const
+{
+ return _b;
+}
+
+QString QFxGridScaledImage::pixmapUrl() const
+{
+ return _pix;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxscalegrid.h b/src/declarative/fx/qfxscalegrid.h
new file mode 100644
index 0000000..9010ce7
--- /dev/null
+++ b/src/declarative/fx/qfxscalegrid.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXSCALEGRID_H
+#define QFXSCALEGRID_H
+
+#include <qfxglobal.h>
+#include <QImage>
+#include <QString>
+#include <QObject>
+#include <qsimplecanvas.h>
+#include <qfxpixmap.h>
+#include <qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QFxScaleGrid : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int left READ left WRITE setLeft)
+ Q_PROPERTY(int top READ top WRITE setTop)
+ Q_PROPERTY(int right READ right WRITE setRight)
+ Q_PROPERTY(int bottom READ bottom WRITE setBottom)
+public:
+ QFxScaleGrid();
+ ~QFxScaleGrid();
+
+ bool isNull() const;
+
+ int left() const { return _left; }
+ void setLeft(int);
+
+ int top() const { return _top; }
+ void setTop(int);
+
+ int right() const { return _right; }
+ void setRight(int);
+
+ int bottom() const { return _bottom; }
+ void setBottom(int);
+
+private:
+ int _left;
+ int _top;
+ int _right;
+ int _bottom;
+};
+
+class Q_DECLARATIVE_EXPORT QFxGridScaledImage
+{
+public:
+ QFxGridScaledImage();
+ QFxGridScaledImage(const QFxGridScaledImage &);
+ QFxGridScaledImage(QIODevice*);
+ QFxGridScaledImage &operator=(const QFxGridScaledImage &);
+ bool isValid() const;
+ int gridLeft() const;
+ int gridRight() const;
+ int gridTop() const;
+ int gridBottom() const;
+
+ QString pixmapUrl() const;
+
+private:
+ int _l;
+ int _r;
+ int _t;
+ int _b;
+ QString _pix;
+};
+QML_DECLARE_TYPE(QFxScaleGrid);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXSCALEGRID_H
diff --git a/src/declarative/fx/qfxshadowfilter.cpp b/src/declarative/fx/qfxshadowfilter.cpp
new file mode 100644
index 0000000..83c1b47
--- /dev/null
+++ b/src/declarative/fx/qfxshadowfilter.cpp
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxshadowfilter.h"
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glsave.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#include <glbasicshaders.h>
+#endif
+
+class QFxShadowFilterPrivate
+
+QT_BEGIN_NAMESPACE
+{
+public:
+ QFxShadowFilterPrivate()
+ : x(0), y(0)
+ {
+ }
+
+ int x;
+ int y;
+};
+
+/*!
+ \qmlclass Shadow
+ \brief The Shadow filter casts a drop shadow.
+ \inherits Filter
+
+ Shadows work on all visual elements - including transparent and masked
+ images.
+
+ \table
+ \row
+ \o \image shadow_example.png
+ \o
+ \qml
+Rect {
+ radius: 5
+ color: "lightsteelblue"
+ width: 100
+ height: 100
+ filter: Shadow {
+ yOffset: 8
+ xOffset: 8
+ }
+}
+
+Image {
+ source: "pics/qtlogo.png"
+ filter: Shadow {
+ yOffset: 8
+ xOffset: 8
+ }
+}
+ \endqml
+ \endtable
+
+ Shadows are only supported when Qt Qt Declarative is compiled for OpenGL ES 2.0.
+ Otherwise the Shadow filter has no effect.
+*/
+
+/*!
+ \internal
+ \class QFxShadowFilter
+ \ingroup group_effects
+ \brief The QFxShadowFilter class allows you to add a shadow to an item.
+*/
+
+QFxShadowFilter::QFxShadowFilter(QObject *parent)
+: QSimpleCanvasFilter(parent), d(new QFxShadowFilterPrivate)
+{
+}
+
+QFxShadowFilter::~QFxShadowFilter()
+{
+ delete d; d = 0;
+}
+
+/*!
+ \qmlproperty int Shadow::xOffset
+ \qmlproperty int Shadow::yOffset
+
+ Specify the x and y offset of the shadow relative to the item.
+*/
+
+int QFxShadowFilter::xOffset() const
+{
+ return d->x;
+}
+
+/*!
+ \property QFxShadowFilter::xOffset
+ \brief the x offset of the shadow relative to the item.
+*/
+void QFxShadowFilter::setXOffset(int offset)
+{
+ if (d->x == offset) return;
+ d->x = offset;
+ emit offsetChanged(d->x, d->y);
+}
+
+/*!
+ \property QFxShadowFilter::yOffset
+ \brief the y offset of the shadow relative to the item.
+*/
+int QFxShadowFilter::yOffset() const
+{
+ return d->y;
+}
+
+void QFxShadowFilter::setYOffset(int offset)
+{
+ if (d->y == offset) return;
+ d->y = offset;
+ emit offsetChanged(d->x, d->y);
+}
+
+QRectF QFxShadowFilter::itemBoundingRect(const QRectF &r) const
+{
+ QRectF rv = r;
+ rv |= r.translated(xOffset(), yOffset());
+ return rv;
+}
+
+void QFxShadowFilter::filterGL(QSimpleCanvasItem::GLPainter &p)
+{
+#if defined(QFX_RENDER_OPENGL2)
+
+ QSimpleCanvasItem *item = this->item();
+
+ QRect r = item->itemBoundingRect();
+
+ QGLFramebufferObject *fbo = renderToFBO();
+
+ float width = r.width();
+ float height = r.height();
+
+ float texWidth = width / float(fbo->width());
+ float texHeight = height / float(fbo->height());
+
+ GLfloat vertices[] = { d->x, height + d->y,
+ width + d->x, height + d->y,
+ d->x, d->y,
+ d->x + width, d->y };
+ GLfloat texVertices[] = { 0, 0,
+ texWidth, 0,
+ 0, texHeight,
+ texWidth, texHeight };
+
+ SingleTextureShadowShader *shader = item->basicShaders()->singleTextureShadow();
+ shader->enable();
+ shader->setOpacity(0.8 * p.activeOpacity);
+ shader->setTransform(p.activeTransform);
+
+ shader->setAttributeArray(SingleTextureShadowShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureShadowShader::TextureCoords, texVertices, 2);
+
+ glBindTexture(GL_TEXTURE_2D, fbo->texture());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(SingleTextureShadowShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShadowShader::TextureCoords);
+
+ releaseFBO(fbo);
+
+ renderToScreen();
+#else
+ Q_UNUSED(p);
+#endif
+}
+
+QML_DEFINE_TYPE(QFxShadowFilter,Shadow);
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxshadowfilter.h b/src/declarative/fx/qfxshadowfilter.h
new file mode 100644
index 0000000..9ba3b7b
--- /dev/null
+++ b/src/declarative/fx/qfxshadowfilter.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXSHADOWFILTER_H
+#define QFXSHADOWFILTER_H
+
+#include <qsimplecanvasfilter.h>
+#include <qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxShadowFilterPrivate;
+class Q_DECLARATIVE_EXPORT QFxShadowFilter : public QSimpleCanvasFilter
+{
+ Q_OBJECT
+ Q_PROPERTY(int xOffset READ xOffset WRITE setXOffset NOTIFY offsetChanged)
+ Q_PROPERTY(int yOffset READ yOffset WRITE setYOffset NOTIFY offsetChanged)
+public:
+ QFxShadowFilter(QObject *parent=0);
+ virtual ~QFxShadowFilter();
+
+ int xOffset() const;
+ void setXOffset(int offset);
+
+ int yOffset() const;
+ void setYOffset(int offset);
+
+Q_SIGNALS:
+ void offsetChanged(int, int);
+
+protected:
+ virtual QRectF itemBoundingRect(const QRectF &) const;
+ virtual void filterGL(QSimpleCanvasItem::GLPainter &p);
+
+private:
+ QFxShadowFilterPrivate *d;
+};
+QML_DECLARE_TYPE(QFxShadowFilter);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // _QFXSHADOWFILTER_H_
diff --git a/src/declarative/fx/qfxtext.cpp b/src/declarative/fx/qfxtext.cpp
new file mode 100644
index 0000000..a43219d
--- /dev/null
+++ b/src/declarative/fx/qfxtext.cpp
@@ -0,0 +1,950 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxtext.h"
+#include "qfxtext_p.h"
+
+#include <private/qtextcontrol_p.h>
+
+#if defined(QFX_RENDER_OPENGL2)
+#include "glbasicshaders.h"
+#endif
+
+#include <qfxperf.h>
+#include <QTextLayout>
+#include <QTextLine>
+#include <QTextDocument>
+#include <QTextCursor>
+#include <QGraphicsSceneMouseEvent>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxText,Text);
+
+/*!
+ \qmlclass Text QFxText
+ \brief The Text item allows you to add formatted text to a scene.
+ \inherits Item
+
+ It can display both plain and rich text. For example:
+
+ \qml
+ Text { text: "Hello World!"; font.family: "Helvetica"; font.size: 24; color: "red" }
+ Text { text: "<b>Hello</b> <i>World!</i>" }
+ \endqml
+
+ \image declarative-text.png
+
+ If height and width are not explicitly set, Text will attempt to determine how
+ much room is needed and set it accordingly. Unless \c wrap is set, it will always
+ prefer width to height (all text will be placed on a single line).
+
+ The \c elide property can alternatively be used to fit a single line of
+ plain text to a set width.
+
+ Text provides read-only text. For editable text, see \l TextEdit.
+*/
+
+/*!
+ \internal
+ \class QFxText
+ \qmlclass Text
+ \ingroup group_coreitems
+
+ \brief The QFxText class provides a formatted text item that you can add to a QFxView.
+
+ Text was designed for read-only text; it does not allow for any text editing.
+ It can display both plain and rich text. For example:
+
+ \qml
+ Text { text: "Hello World!"; font.family: "Helvetica"; font.size: 24; color: "red" }
+ Text { text: "<b>Hello</b> <i>World!</i>" }
+ \endqml
+
+ \image text.png
+
+ If height and width are not explicitly set, Text will attempt to determine how
+ much room is needed and set it accordingly. Unless \c wrap is set, it will always
+ prefer width to height (all text will be placed on a single line).
+
+ The \c elide property can alternatively be used to fit a line of plain text to a set width.
+
+ A QFxText object can be instantiated in Qml using the tag \c Text.
+*/
+QFxText::QFxText(QFxItem *parent)
+ : QFxItem(*(new QFxTextPrivate), parent)
+{
+ Q_D(QFxText);
+ d->init();
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setOptions(SimpleItem | HasContents | QFxText::MouseEvents);
+}
+
+QFxText::QFxText(QFxTextPrivate &dd, QFxItem *parent)
+ : QFxItem(dd, parent)
+{
+ Q_D(QFxText);
+ d->init();
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setOptions(SimpleItem | HasContents | QFxText::MouseEvents);
+}
+
+QFxText::~QFxText()
+{
+}
+
+/*!
+ \qmlproperty string Text::font.family
+ \qmlproperty bool Text::font.bold
+ \qmlproperty bool Text::font.italic
+ \qmlproperty real Text::font.size
+
+ Set the Text's font attributes.
+
+ \note \c font.size sets the font's point size (not pixel size).
+*/
+
+/*!
+ \property QFxText::font
+ \brief the font used to display the text.
+*/
+
+QmlFont *QFxText::font()
+{
+ Q_D(QFxText);
+ return d->font();
+}
+
+void QFxText::setText(const QString &n)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::QFxText_setText> st;
+#endif
+ Q_D(QFxText);
+ if (d->text == n)
+ return;
+
+ d->richText = Qt::mightBeRichText(n); // ### what's the cost?
+ if (d->richText) {
+ if (!d->doc)
+ {
+ d->control = new QTextControl(this);
+ d->control->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ d->doc = d->control->document();
+ d->doc->setDocumentMargin(0);
+ }
+ d->doc->setHtml(n);
+ }
+
+ d->text = n;
+ d->imgDirty = true;
+ d->updateSize();
+ emit textChanged(d->text);
+ update();
+}
+
+/*!
+ \qmlproperty string Text::text
+ \default
+
+ The text to display. Text supports both plain and rich text strings.
+
+ The item will try to automatically determine whether the text should
+ be treated as rich text. This determination is made using Qt::mightBeRichText().
+*/
+QString QFxText::text() const
+{
+ Q_D(const QFxText);
+ return d->text;
+}
+
+void QFxText::setColor(const QColor &color)
+{
+ Q_D(QFxText);
+ if (d->color == color)
+ return;
+
+ d->imgDirty = true;
+ d->color = color;
+ update();
+}
+
+/*!
+ \qmlproperty color Text::color
+
+ The text color.
+
+ \qml
+ //green text using hexadecimal notation
+ Text { color: "#00FF00"; ... }
+
+ //steelblue text using SVG color name
+ Text { color: "steelblue"; ... }
+ \endqml
+*/
+
+QColor QFxText::color() const
+{
+ Q_D(const QFxText);
+ return d->color;
+}
+
+/*!
+ \qmlproperty enumeration Text::style
+
+ Set an additional text style.
+
+ Supported text styles are \c Normal, \c Outline, \c Raised and \c Sunken.
+
+ \qml
+ HorizontalLayout {
+ Text { font.size: 24; text: "Normal" }
+ Text { font.size: 24; text: "Raised"; style: "Raised"; styleColor: "#AAAAAA" }
+ Text { font.size: 24; text: "Outline"; style: "Outline"; styleColor: "red" }
+ Text { font.size: 24; text: "Sunken"; style: "Sunken"; styleColor: "#AAAAAA" }
+ }
+ \endqml
+
+ \image declarative-textstyle.png
+*/
+
+/*!
+ \property QFxText::style
+ \brief an additional style of the text to display.
+
+ By default, the text style is Normal.
+
+ \note This property is used to support text styles not natively
+ handled by QFont or QPainter::drawText().
+*/
+QFxText::TextStyle QFxText::style() const
+{
+ Q_D(const QFxText);
+ return d->style;
+}
+
+void QFxText::setStyle(QFxText::TextStyle style)
+{
+ Q_D(QFxText);
+ if (d->style == style)
+ return;
+
+ d->imgDirty = true;
+ d->style = style;
+ update();
+}
+
+void QFxText::setStyleColor(const QColor &color)
+{
+ Q_D(QFxText);
+ if (d->styleColor == color)
+ return;
+
+ d->imgDirty = true;
+ d->styleColor = color;
+ update();
+}
+
+/*!
+ \qmlproperty color Text::styleColor
+
+ Defines the secondary color used by text styles.
+
+ \c styleColor is used as the outline color for outlined text, and as the
+ shadow color for raised or sunken text. If no style has been set, it is not
+ used at all.
+ */
+QColor QFxText::styleColor() const
+{
+ Q_D(const QFxText);
+ return d->styleColor;
+}
+
+/*!
+ \qmlproperty enumeration Text::hAlign
+ \qmlproperty enumeration Text::vAlign
+
+ Sets the horizontal and vertical alignment of the text within the Text items
+ width and height. By default, the text is top-left aligned.
+
+ The valid values for \c hAlign are \c AlignLeft, \c AlignRight and
+ \c AlignHCenter. The valid values for \c vAlign are \c AlignTop, \c AlignBottom
+ and \c AlignVCenter.
+*/
+
+/*!
+ \property QFxText::hAlign
+ \brief the horizontal alignment of the text.
+
+ Valid values are \c AlignLeft, \c AlignRight, and \c AlignHCenter. The default value is \c AlignLeft.
+*/
+QFxText::HAlignment QFxText::hAlign() const
+{
+ Q_D(const QFxText);
+ return d->hAlign;
+}
+
+void QFxText::setHAlign(HAlignment align)
+{
+ Q_D(QFxText);
+ d->hAlign = align;
+}
+
+/*!
+ \property QFxText::vAlign
+ \brief the vertical alignment of the text.
+
+ Valid values are \c AlignTop, \c AlignBottom, and \c AlignVCenter. The default value is \c AlignTop.
+*/
+QFxText::VAlignment QFxText::vAlign() const
+{
+ Q_D(const QFxText);
+ return d->vAlign;
+}
+
+void QFxText::setVAlign(VAlignment align)
+{
+ Q_D(QFxText);
+ d->vAlign = align;
+}
+
+/*!
+ \qmlproperty bool Text::wrap
+
+ Set this property to wrap the text to the Text item's width. The text will only
+ wrap if an explicit width has been set.
+
+ Wrapping is done on word boundaries (i.e. it is a "word-wrap"). If the text cannot be
+ word-wrapped to the specified width it will be partially drawn outside of the item's bounds.
+ If this is undesirable then enable clipping on the item (Item::clip).
+
+ Wrapping is off by default.
+*/
+//### Future may provide choice of wrap modes, such as QTextOption::WrapAtWordBoundaryOrAnywhere
+bool QFxText::wrap() const
+{
+ Q_D(const QFxText);
+ return d->wrap;
+}
+
+void QFxText::setWrap(bool w)
+{
+ Q_D(QFxText);
+ if (w == d->wrap)
+ return;
+
+ d->wrap = w;
+
+ d->imgDirty = true;
+ d->updateSize();
+}
+
+/*!
+ \qmlproperty Qt::TextElideMode Text::elide
+
+ Set this property to elide parts of the text fit to the Text item's width.
+ The text will only elide if an explicit width has been set.
+
+ This property cannot be used with wrap enabled or with rich text.
+
+ Eliding can be ElideNone, ElideLeft, ElideMiddle, or ElideRight.
+
+ ElideNone is the default.
+*/
+Qt::TextElideMode QFxText::elideMode() const
+{
+ Q_D(const QFxText);
+ return d->elideMode;
+}
+
+void QFxText::setElideMode(Qt::TextElideMode mode)
+{
+ Q_D(QFxText);
+ if (mode == d->elideMode)
+ return;
+
+ d->elideMode = mode;
+
+ d->imgDirty = true;
+ d->updateSize();
+}
+
+
+QString QFxText::activeLink() const
+{
+ Q_D(const QFxText);
+ return d->activeLink;
+}
+
+void QFxText::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QFxText);
+ if (newGeometry.width() != oldGeometry.width()) {
+ if (d->wrap || d->elideMode != Qt::ElideNone) {
+ d->imgDirty = true;
+ d->updateSize();
+ }
+ }
+ QFxItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+
+void QFxText::fontChanged()
+{
+ Q_D(QFxText);
+ d->imgDirty = true;
+ d->updateSize();
+ emit update();
+}
+
+void QFxTextPrivate::updateSize()
+{
+ Q_Q(QFxText);
+ if (q->isComponentComplete()) {
+ if (text.isEmpty()) {
+ return;
+ }
+ QFont f; if (_font) f = _font->font();
+ QFontMetrics fm(f);
+ int dy = q->height();
+
+ QString tmp;
+ QSize size(0, 0);
+
+ //setup instance of QTextLayout for all cases other than richtext
+ if (!richText)
+ {
+ tmp = text;
+ tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ singleline = !tmp.contains(QChar::LineSeparator);
+ if (singleline && elideMode != Qt::ElideNone && q->widthValid())
+ tmp = fm.elidedText(tmp,elideMode,q->width()); // XXX still worth layout...?
+ QTextLayout layout;
+ layout.setFont(f);
+ layout.setText(tmp);
+ size = setupTextLayout(&layout);
+ }
+ if (richText) {
+ singleline = false; // richtext can't elide or be optimized for single-line case
+ doc->setDefaultFont(f);
+ QTextOption option((Qt::Alignment)int(hAlign | vAlign));
+ if (wrap)
+ option.setWrapMode(QTextOption::WordWrap);
+ else
+ option.setWrapMode(QTextOption::NoWrap);
+ doc->setDefaultTextOption(option);
+ if (wrap && !q->heightValid() && q->widthValid())
+ doc->setTextWidth(q->width());
+ else
+ doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug)
+ dy -= (int)doc->size().height();
+ } else {
+ dy -= size.height();
+ }
+ int yoff = 0;
+
+ if (q->heightValid()) {
+ if (vAlign == QFxText::AlignBottom)
+ yoff = dy;
+ else if (vAlign == QFxText::AlignVCenter)
+ yoff = dy/2;
+ }
+ q->setBaselineOffset(fm.ascent() + yoff);
+
+ if (!q->widthValid()) {
+ int newWidth = (richText ? (int)doc->idealWidth() : size.width());
+ q->setImplicitWidth(newWidth);
+ }
+ if (!q->heightValid()) {
+ if (richText) {
+ q->setImplicitHeight((int)doc->size().height());
+ } else {
+ q->setImplicitHeight(size.height());
+ }
+ }
+ } else {
+ dirty = true;
+ }
+}
+
+// ### text layout handling should be profiled and optimized as needed
+// what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine);
+
+void QFxText::dump(int depth)
+{
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << propertyInfo();
+ QFxItem::dump(depth);
+}
+
+QString QFxText::propertyInfo() const
+{
+ Q_D(const QFxText);
+ return QChar(QLatin1Char('\"')) + d->text + QChar(QLatin1Char('\"'));
+}
+
+void QFxTextPrivate::drawOutline()
+{
+ QImage img = QImage(imgCache.size(), QImage::Format_ARGB32_Premultiplied);
+ QPainter ppm(&img);
+ img.fill(qRgba(0, 0, 0, 0));
+
+ QPoint pos(imgCache.rect().topLeft());
+ pos += QPoint(-1, 0);
+ ppm.drawImage(pos, imgStyleCache);
+ pos += QPoint(2, 0);
+ ppm.drawImage(pos, imgStyleCache);
+ pos += QPoint(-1, -1);
+ ppm.drawImage(pos, imgStyleCache);
+ pos += QPoint(0, 2);
+ ppm.drawImage(pos, imgStyleCache);
+
+ pos += QPoint(0, -1);
+ QPainter &p = ppm;
+ p.drawImage(pos, imgCache);
+
+ imgCache = QSimpleCanvasConfig::toImage(img);
+}
+
+void QFxTextPrivate::drawOutline(int yOffset)
+{
+ QImage img = QImage(imgCache.size(), QImage::Format_ARGB32_Premultiplied);
+ QPainter ppm(&img);
+ img.fill(qRgba(0, 0, 0, 0));
+
+ QPoint pos(imgCache.rect().topLeft());
+ pos += QPoint(0, yOffset);
+ ppm.drawImage(pos, imgStyleCache);
+
+ pos += QPoint(0, -yOffset);
+ QPainter &p = ppm;
+ p.drawImage(pos, imgCache);
+
+ imgCache = QSimpleCanvasConfig::toImage(img);
+}
+
+QSize QFxTextPrivate::setupTextLayout(QTextLayout *layout)
+{
+ Q_Q(QFxText);
+ layout->setCacheEnabled(true);
+
+ QFont f; if (_font) f = _font->font();
+ QFontMetrics fm = QFontMetrics(f);
+
+ int leading = fm.leading();
+ int height = 0;
+ qreal widthUsed = 0;
+ qreal lineWidth = 0;
+
+ //set manual width
+ if ((wrap || elideMode != Qt::ElideNone) && q->widthValid())
+ lineWidth = q->width();
+
+ layout->beginLayout();
+
+ while (1) {
+ QTextLine line = layout->createLine();
+ if (!line.isValid())
+ break;
+
+ if ((wrap || elideMode != Qt::ElideNone) && q->widthValid())
+ line.setLineWidth(lineWidth);
+ }
+ layout->endLayout();
+
+ if (layout->lineCount() == 1)
+ height -= leading;
+
+ for (int i = 0; i < layout->lineCount(); ++i) {
+ QTextLine line = layout->lineAt(i);
+ widthUsed = qMax(widthUsed, line.naturalTextWidth());
+ line.setPosition(QPointF(0, height));
+ height += int(line.height());
+ }
+ return QSize((int)widthUsed, height);
+}
+
+QImage QFxTextPrivate::wrappedTextImage(bool drawStyle)
+{
+ //do layout
+ Q_Q(const QFxText);
+ QFont f; if (_font) f = _font->font();
+ QString tmp = text;
+ if (singleline && elideMode != Qt::ElideNone && q->widthValid()) {
+ QFontMetrics fm(f);
+ tmp = fm.elidedText(tmp,elideMode,q->width()); // XXX still worth layout...?
+ }
+ tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ QTextLayout textLayout(tmp, f);
+ QSize size = setupTextLayout(&textLayout);
+
+ int x = 0;
+ for (int i = 0; i < textLayout.lineCount(); ++i) {
+ QTextLine line = textLayout.lineAt(i);
+ if (hAlign == QFxText::AlignLeft) {
+ x = 0;
+ } else if (hAlign == QFxText::AlignRight) {
+ x = size.width() - (int)line.naturalTextWidth();
+ } else if (hAlign == QFxText::AlignHCenter) {
+ x = (size.width() - (int)line.naturalTextWidth()) / 2;
+ }
+ line.setPosition(QPoint(x, (int)line.y()));
+ }
+
+ //paint text
+ QImage img(size, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+ QPainter p(&img);
+ if (drawStyle) {
+ p.setPen(styleColor);
+ }
+ else
+ p.setPen(color);
+ p.setFont(f);
+ textLayout.draw(&p, QPointF(0, 0));
+ return img;
+}
+
+QImage QFxTextPrivate::richTextImage(bool drawStyle)
+{
+ QSize size = doc->size().toSize();
+
+ //paint text
+ QImage img(size, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+ QPainter p(&img);
+
+ if (drawStyle) {
+ QPalette pal = control->palette();
+ pal.setColor(QPalette::Text, styleColor);
+ control->setPalette(pal);
+ QTextOption colorOption;
+ colorOption.setFlags(QTextOption::SuppressColors);
+ doc->setDefaultTextOption(colorOption);
+ } else {
+ QPalette pal = control->palette();
+ pal.setColor(QPalette::Text, color);
+ control->setPalette(pal);
+ }
+ control->drawContents(&p, QRectF(QPointF(0, 0), QSizeF(size)));
+ if (drawStyle)
+ doc->setDefaultTextOption(QTextOption());
+ return img;
+}
+
+void QFxTextPrivate::checkImgCache()
+{
+ if (!imgDirty)
+ return;
+
+ bool empty = text.isEmpty();
+ if (empty) {
+ imgCache = QSimpleCanvasConfig::Image();
+ imgStyleCache = QImage();
+ } else if (richText) {
+ imgCache = QSimpleCanvasConfig::toImage(richTextImage(false));
+ if (style != QFxText::Normal)
+ imgStyleCache = richTextImage(true); //### should use styleColor
+ } else {
+ imgCache = QSimpleCanvasConfig::toImage(wrappedTextImage(false));
+ if (style != QFxText::Normal)
+ imgStyleCache = wrappedTextImage(true); //### should use styleColor
+ }
+ if (!empty)
+ switch (style) {
+ case QFxText::Outline:
+ drawOutline();
+ break;
+ case QFxText::Sunken:
+ drawOutline(-1);
+ break;
+ case QFxText::Raised:
+ drawOutline(1);
+ break;
+ default:
+ break;
+ }
+
+#if defined(QFX_RENDER_OPENGL)
+ tex.setImage(imgCache);
+#endif
+
+ imgDirty = false;
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+void QFxText::paintContents(QPainter &p)
+{
+ Q_D(QFxText);
+ d->checkImgCache();
+ if (d->imgCache.isNull())
+ return;
+
+ int w = width();
+ int h = height();
+
+ int x = 0;
+ int y = 0;
+
+ switch (d->hAlign) {
+ case AlignLeft:
+ x = 0;
+ break;
+ case AlignRight:
+ x = w - d->imgCache.width();
+ break;
+ case AlignHCenter:
+ x = (w - d->imgCache.width()) / 2;
+ break;
+ }
+
+ switch (d->vAlign) {
+ case AlignTop:
+ y = 0;
+ break;
+ case AlignBottom:
+ y = h - d->imgCache.height();
+ break;
+ case AlignVCenter:
+ y = (h - d->imgCache.height()) / 2;
+ break;
+ }
+
+ p.drawImage(x, y, d->imgCache);
+}
+
+#elif defined(QFX_RENDER_OPENGL2)
+void QFxText::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxText);
+ d->checkImgCache();
+ if (d->imgCache.isNull())
+ return;
+
+ int w = width();
+ int h = height();
+
+ float x = 0;
+ float y = 0;
+
+ switch (d->hAlign) {
+ case AlignLeft:
+ x = 0;
+ break;
+ case AlignRight:
+ x = w - d->imgCache.width();
+ break;
+ case AlignHCenter:
+ x = (w - d->imgCache.width()) / 2;
+ break;
+ }
+
+ switch (d->vAlign) {
+ case AlignTop:
+ y = 0;
+ break;
+ case AlignBottom:
+ y = h - d->imgCache.height();
+ break;
+ case AlignVCenter:
+ y = (h - d->imgCache.height()) / 2;
+ break;
+ }
+
+ float widthV = d->imgCache.width();
+ float heightV = d->imgCache.height();
+
+ QGLShaderProgram *shader = p.useTextureShader();
+
+ GLfloat vertices[] = { x, y + heightV,
+ x + widthV, y + heightV,
+ x, y,
+ x + widthV, y };
+
+ GLfloat texVertices[] = { 0, 0,
+ 1, 0,
+ 0, 1,
+ 1, 1 };
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2);
+
+ glBindTexture(GL_TEXTURE_2D, d->tex.texture());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+}
+
+#elif defined(QFX_RENDER_OPENGL)
+void QFxText::paintGLContents(GLPainter &p)
+{
+ Q_D(QFxText);
+ d->checkImgCache();
+ if (d->imgCache.isNull())
+ return;
+
+ int w = width();
+ int h = height();
+
+ float x = 0;
+ float y = 0;
+
+ switch (d->hAlign) {
+ case AlignLeft:
+ x = 0;
+ break;
+ case AlignRight:
+ x = w - d->imgCache.width();
+ break;
+ case AlignHCenter:
+ x = (w - d->imgCache.width()) / 2;
+ break;
+ }
+
+ switch (d->vAlign) {
+ case AlignTop:
+ y = 0;
+ break;
+ case AlignBottom:
+ y = h - d->imgCache.height();
+ break;
+ case AlignVCenter:
+ y = (h - d->imgCache.height()) / 2;
+ break;
+ }
+
+ float widthV = d->imgCache.width();
+ float heightV = d->imgCache.height();
+
+ GLfloat vertices[] = { x, y + heightV,
+ x + widthV, y + heightV,
+ x, y,
+ x + widthV, y };
+
+ GLfloat texVertices[] = { 0, 0,
+ 1, 0,
+ 0, 1,
+ 1, 1 };
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(p.activeTransform.data());
+ glEnable(GL_TEXTURE_2D);
+ if (p.activeOpacity == 1.) {
+ GLint i = GL_REPLACE;
+ glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i);
+ } else {
+ GLint i = GL_MODULATE;
+ glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i);
+ glColor4f(1, 1, 1, p.activeOpacity);
+ }
+
+ glBindTexture(GL_TEXTURE_2D, d->tex.texture());
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glTexCoordPointer(2, GL_FLOAT, 0, texVertices);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D);
+}
+
+#endif
+
+void QFxText::componentComplete()
+{
+ Q_D(QFxText);
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::TextComponentComplete> cc;
+#endif
+ QFxItem::componentComplete();
+ if (d->dirty) {
+ d->updateSize();
+ d->dirty = false;
+ }
+}
+
+/*!
+ \overload
+ Handles the given mouse \a event.
+ */
+void QFxText::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxText);
+
+ if (!d->richText || !d->doc || d->control->anchorAt(event->pos()).isEmpty()) {
+ event->setAccepted(false);
+ d->activeLink = QString();
+ } else {
+ d->activeLink = d->control->anchorAt(event->pos());
+ }
+
+ // ### may malfunction if two of the same links are clicked & dragged onto each other)
+
+ if (!event->isAccepted())
+ QFxItem::mousePressEvent(event);
+
+}
+
+/*!
+ \overload
+ Handles the given mouse \a event.
+ */
+void QFxText::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxText);
+
+ // ### confirm the link, and send a signal out
+ if (d->richText && d->doc && d->activeLink == d->control->anchorAt(event->pos()))
+ emit linkActivated(d->activeLink);
+ else
+ event->setAccepted(false);
+
+ if (!event->isAccepted())
+ QFxItem::mouseReleaseEvent(event);
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxtext.h b/src/declarative/fx/qfxtext.h
new file mode 100644
index 0000000..0de884b
--- /dev/null
+++ b/src/declarative/fx/qfxtext.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXTEXT_H
+#define QFXTEXT_H
+
+#include <qfxitem.h>
+#include <qmlfont.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxTextPrivate;
+class Q_DECLARATIVE_EXPORT QFxText : public QFxItem
+{
+ Q_OBJECT
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(VAlignment)
+ Q_ENUMS(TextStyle)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QmlFont *font READ font)
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+ Q_PROPERTY(TextStyle style READ style WRITE setStyle)
+ Q_PROPERTY(QColor styleColor READ styleColor WRITE setStyleColor)
+ Q_PROPERTY(HAlignment hAlign READ hAlign WRITE setHAlign)
+ Q_PROPERTY(VAlignment vAlign READ vAlign WRITE setVAlign)
+ Q_PROPERTY(bool wrap READ wrap WRITE setWrap)
+ Q_PROPERTY(Qt::TextElideMode elide READ elideMode WRITE setElideMode)
+ Q_PROPERTY(QString activeLink READ activeLink);
+ Q_CLASSINFO("DefaultProperty", "text")
+
+public:
+ QFxText(QFxItem *parent=0);
+ ~QFxText();
+
+ enum HAlignment { AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter };
+ enum VAlignment { AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter };
+ enum TextStyle { Normal,
+ Outline,
+ Raised,
+ Sunken };
+
+ QString text() const;
+ void setText(const QString &);
+
+ QmlFont *font();
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ TextStyle style() const;
+ void setStyle(TextStyle style);
+
+ QColor styleColor() const;
+ void setStyleColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+
+ VAlignment vAlign() const;
+ void setVAlign(VAlignment align);
+
+ bool wrap() const;
+ void setWrap(bool w);
+
+ Qt::TextElideMode elideMode() const;
+ void setElideMode(Qt::TextElideMode);
+
+ QString activeLink() const;
+
+ virtual void dump(int depth);
+ virtual QString propertyInfo() const;
+
+#if defined(QFX_RENDER_QPAINTER)
+ void paintContents(QPainter &p);
+#elif defined(QFX_RENDER_OPENGL)
+ void paintGLContents(GLPainter &);
+#endif
+
+ virtual void componentComplete();
+
+Q_SIGNALS:
+ void textChanged(const QString &text);
+ void linkActivated(const QString &link);
+
+private Q_SLOTS:
+ //### should be in QFxTextPrivate?
+ void fontChanged();
+
+protected:
+ QFxText(QFxTextPrivate &dd, QFxItem *parent);
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+private:
+ Q_DISABLE_COPY(QFxText)
+ Q_DECLARE_PRIVATE(QFxText)
+};
+QML_DECLARE_TYPE(QFxText);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxtext_p.h b/src/declarative/fx/qfxtext_p.h
new file mode 100644
index 0000000..4296891
--- /dev/null
+++ b/src/declarative/fx/qfxtext_p.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXTEXT_P_H
+#define QFXTEXT_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 "qfxitem.h"
+#include "qfxitem_p.h"
+#include "qml.h"
+
+#if defined(QFX_RENDER_OPENGL)
+#include "gltexture.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QTextLayout;
+class QTextDocument;
+class QTextControl;
+
+class QFxTextPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxText)
+public:
+ QFxTextPrivate()
+ : _font(0), color((QRgb)0), style(QFxText::Normal), imgDirty(true), hAlign(QFxText::AlignLeft), vAlign(QFxText::AlignTop), elideMode(Qt::ElideNone), dirty(false), wrap(false), richText(false), singleline(false), control(0), doc(0)
+ {
+ }
+
+ ~QFxTextPrivate()
+ {
+ delete _font;
+ }
+
+ void init()
+ {
+ }
+
+ void updateSize();
+ void checkImgCache();
+
+ void drawOutline();
+ void drawOutline(int yOffset);
+
+ QImage wrappedTextImage(bool drawStyle);
+ QImage richTextImage(bool drawStyle);
+ QSize setupTextLayout(QTextLayout *layout);
+
+ QString text;
+ QmlFont *font()
+ {
+ if (!_font) {
+ Q_Q(QFxText);
+ _font = new QmlFont;
+ QObject::connect(_font, SIGNAL(updated()), q, SLOT(fontChanged()));
+ }
+ return _font;
+ }
+
+ QmlFont *_font;
+ QColor color;
+ QFxText::TextStyle style;
+ QColor styleColor;
+ QString activeLink;
+ bool imgDirty;
+#if defined(QFX_RENDER_OPENGL)
+ GLTexture tex;
+#endif
+ QSimpleCanvasConfig::Image imgCache;
+ QImage imgStyleCache;
+ QFxText::HAlignment hAlign;
+ QFxText::VAlignment vAlign;
+ Qt::TextElideMode elideMode;
+ bool dirty;
+ bool wrap;
+ bool richText;
+ bool singleline;
+ QTextControl *control;
+ QTextDocument *doc;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp
new file mode 100644
index 0000000..35b1173
--- /dev/null
+++ b/src/declarative/fx/qfxtextedit.cpp
@@ -0,0 +1,887 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qfxtextedit.h>
+#include "qfxtextedit_p.h"
+
+#include <private/qtextcontrol_p.h>
+
+#if defined(QFX_RENDER_OPENGL2)
+#include "glbasicshaders.h"
+#endif
+
+#include <qfxperf.h>
+#include <QTextLayout>
+#include <QTextLine>
+#include <QTextDocument>
+#include <QGraphicsSceneMouseEvent>
+
+#include <QDebug>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxTextEdit, TextEdit);
+
+/*!
+ \qmlclass TextEdit
+ \brief The TextEdit item allows you to add editable formatted text to a scene.
+
+ It can display both plain and rich text. For example:
+
+ \qml
+TextEdit {
+ id: edit
+ text: "<b>Hello</b> <i>World!</i>"
+ focus: true
+ focusable: true
+ font.family: "Helvetica"
+ font.size: 20
+ color: "blue"
+ width: 240
+}
+ \endqml
+
+ \image declarative-textedit.gif
+
+ \sa Text
+*/
+
+/*!
+ \internal
+ \class QFxTextEdit
+ \qmlclass TextEdit
+ \ingroup group_coreitems
+
+ \brief The QFxTextEdit class provides an editable formatted text item that you can add to a QFxView.
+
+ It can display both plain and rich text.
+
+ \image declarative-textedit.png
+
+ A QFxTextEdit object can be instantiated in Qml using the tag \c &lt;TextEdit&gt;.
+*/
+
+/*!
+ Constructs a new QFxTextEdit.
+*/
+QFxTextEdit::QFxTextEdit(QFxItem *parent)
+: QFxPaintedItem(*(new QFxTextEditPrivate), parent)
+{
+ Q_D(QFxTextEdit);
+ d->init();
+}
+
+/*!
+\internal
+*/
+QFxTextEdit::QFxTextEdit(QFxTextEditPrivate &dd, QFxItem *parent)
+ : QFxPaintedItem(dd, parent)
+{
+ Q_D(QFxTextEdit);
+ d->init();
+}
+
+QString QFxTextEdit::text() const
+{
+ Q_D(const QFxTextEdit);
+
+ if (d->richText)
+ return d->document->toHtml();
+ else
+ return d->document->toPlainText();
+}
+
+/*!
+ \qmlproperty font TextEdit::font
+
+ Set the TextEdit's font attributes. \c font.size sets the font's point size.
+*/
+
+/*!
+ \qmlproperty string TextEdit::text
+ \default
+
+ The text to display. If the text format is AutoText the text edit will
+ automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+*/
+
+/*!
+ \property QFxTextEdit::text
+ \brief the text edit's text
+
+ If the text format is set to AutoText the text edit will try to
+ automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+
+ \sa textFormat
+*/
+
+void QFxTextEdit::setText(const QString &text)
+{
+ Q_D(QFxTextEdit);
+ d->text = text;
+ d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text));
+ if (d->richText) {
+ d->control->setHtml(text);
+ } else {
+ d->control->setPlainText(text);
+ }
+ q_textChanged();
+ updateSize();
+}
+
+/*!
+ \qmlproperty enumeration TextEdit::textFormat
+
+ The way the text property should be displayed.
+
+ Supported text formats are \c AutoText, \c PlainText and \c RichText.
+
+ The default is AutoText. If the text format is AutoText the text edit
+ edit will automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+
+ \table
+ \row
+ \o
+ \qml
+VerticalLayout {
+ TextEdit {
+ font.size: 24
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.size: 24
+ textFormat: "RichText"
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.size: 24
+ textFormat: "PlainText"
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+}
+ \endqml
+ \o \image declarative-textformat.png
+ \endtable
+*/
+
+/*!
+ \property QFxTextEdit::textFormat
+ \brief this property describes how the text set on the text edit
+ should be interpreted.
+
+ Valid values are \c AutoText, \c PlainText and \c RichText. The
+ default value is \c AutoText, meaning the text edit will attempt
+ to guess how the text should be interpreted using the
+ Qt::mightBeRichText() function.
+
+ \sa text
+*/
+
+QFxTextEdit::TextFormat QFxTextEdit::textFormat() const
+{
+ Q_D(const QFxTextEdit);
+ return d->format;
+}
+
+void QFxTextEdit::setTextFormat(TextFormat format)
+{
+ Q_D(QFxTextEdit);
+ if (format == d->format)
+ return;
+ bool wasRich = d->richText;
+ d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
+
+ if (wasRich && !d->richText) {
+ d->control->setPlainText(d->text);
+ updateSize();
+ } else if (!wasRich && d->richText) {
+ d->control->setHtml(d->text);
+ updateSize();
+ }
+ d->format = format;
+}
+
+/*!
+ \property QFxTextEdit::font
+ \brief the text edit's default font
+*/
+
+QmlFont *QFxTextEdit::font()
+{
+ Q_D(QFxTextEdit);
+ return &(d->font);
+}
+
+/*!
+ \qmlproperty color TextEdit::color
+
+ The text color.
+
+ \qml
+// green text using hexadecimal notation
+TextEdit { color: "#00FF00"; ... }
+
+// steelblue text using SVG color name
+TextEdit { color: "steelblue"; ... }
+ \endqml
+*/
+
+/*!
+ \property QFxTextEdit::color
+ \brief the text edit's default text color
+*/
+QColor QFxTextEdit::color() const
+{
+ Q_D(const QFxTextEdit);
+ return d->color;
+}
+
+void QFxTextEdit::setColor(const QColor &color)
+{
+ Q_D(QFxTextEdit);
+ if (d->color == color)
+ return;
+
+ clearCache();
+ d->color = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::Text, color);
+ d->control->setPalette(pal);
+ update();
+}
+
+/*!
+ \qmlproperty color TextEdit::highlightColor
+
+ The text highlight color, used behind selections.
+*/
+
+/*!
+ \property QFxTextEdit::highlightColor
+ \brief the text edit's default text highlight color
+*/
+QColor QFxTextEdit::highlightColor() const
+{
+ Q_D(const QFxTextEdit);
+ return d->highlightColor;
+}
+
+void QFxTextEdit::setHighlightColor(const QColor &color)
+{
+ Q_D(QFxTextEdit);
+ if (d->highlightColor == color)
+ return;
+
+ clearCache();
+ d->highlightColor = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::Highlight, color);
+ d->control->setPalette(pal);
+ update();
+}
+
+/*!
+ \qmlproperty enumeration TextEdit::hAlign
+ \qmlproperty enumeration TextEdit::vAlign
+
+ Sets the horizontal and vertical alignment of the text within the TextEdit items
+ width and height. By default, the text is top-left aligned.
+
+ The valid values for \c hAlign are \c AlignLeft, \c AlignRight and
+ \c AlignHCenter. The valid values for \c vAlign are \c AlignTop, \c AlignBottom
+ and \c AlignVCenter.
+*/
+
+/*!
+ \property QFxTextEdit::hAlign
+ \brief the horizontal alignment of the text.
+
+ Valid values are \c AlignLeft, \c AlignRight, and \c AlignHCenter. The default value is \c AlignLeft.
+*/
+QFxTextEdit::HAlignment QFxTextEdit::hAlign() const
+{
+ Q_D(const QFxTextEdit);
+ return d->hAlign;
+}
+
+void QFxTextEdit::setHAlign(QFxTextEdit::HAlignment alignment)
+{
+ Q_D(QFxTextEdit);
+ if (alignment == d->hAlign)
+ return;
+ d->hAlign = alignment;
+ d->updateDefaultTextOption();
+ updateSize();
+}
+
+/*!
+ \property QFxTextEdit::vAlign
+ \brief the vertical alignment of the text.
+
+ Valid values are \c AlignTop, \c AlignBottom, and \c AlignVCenter. The default value is \c AlignTop.
+*/
+QFxTextEdit::VAlignment QFxTextEdit::vAlign() const
+{
+ Q_D(const QFxTextEdit);
+ return d->vAlign;
+}
+
+void QFxTextEdit::setVAlign(QFxTextEdit::VAlignment alignment)
+{
+ Q_D(QFxTextEdit);
+ if (alignment == d->vAlign)
+ return;
+ d->vAlign = alignment;
+ d->updateDefaultTextOption();
+ updateSize();
+}
+
+bool QFxTextEdit::wrap() const
+{
+ Q_D(const QFxTextEdit);
+ return d->wrap;
+}
+
+/*!
+ \qmlproperty bool TextEdit::wrap
+
+ Set this property to wrap the text to the TextEdit item's width.
+ The text will only wrap if an explicit width has been set.
+
+ Wrapping is done on word boundaries (i.e. it is a "word-wrap"). Wrapping is off by default.
+*/
+
+/*!
+ \property QFxTextEdit::wrap
+ \brief If true the text edit wraps text based on the width of the
+ text edit.
+*/
+void QFxTextEdit::setWrap(bool w)
+{
+ Q_D(QFxTextEdit);
+ if (w == d->wrap)
+ return;
+ d->wrap = w;
+ d->updateDefaultTextOption();
+ updateSize();
+}
+
+/*!
+ \property QFxTextEdit::cursorVisible
+ \brief If true the text edit shows a cursor.
+
+ This property is set and unset when the text edit gets focus, but it can also
+ be set directly (useful, for example, if a KeyProxy might forward keys to it).
+*/
+bool QFxTextEdit::isCursorVisible() const
+{
+ Q_D(const QFxTextEdit);
+ return d->cursorVisible;
+}
+
+void QFxTextEdit::setCursorVisible(bool on)
+{
+ Q_D(QFxTextEdit);
+ if (d->cursorVisible == on)
+ return;
+ d->cursorVisible = on;
+ QFocusEvent focusEvent(on ? QEvent::FocusIn : QEvent::FocusOut);
+ d->control->processEvent(&focusEvent, QPointF(0, 0));
+}
+
+/*!
+ \qmlproperty bool TextEdit::focusOnPress
+
+ Whether the TextEdit should gain focus on a mouse press. By default this is
+ set to false;
+*/
+bool QFxTextEdit::focusOnPress() const
+{
+ Q_D(const QFxTextEdit);
+ return d->focusOnPress;
+}
+
+void QFxTextEdit::setFocusOnPress(bool on)
+{
+ Q_D(QFxTextEdit);
+ if (d->focusOnPress == on)
+ return;
+ d->focusOnPress = on;
+}
+
+void QFxTextEdit::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ if (newGeometry.width() != oldGeometry.width())
+ updateSize();
+ QFxPaintedItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+/*!
+ \internal
+*/
+void QFxTextEdit::dump(int depth)
+{
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << propertyInfo();
+ QFxPaintedItem::dump(depth);
+}
+
+/*!
+ \internal
+*/
+QString QFxTextEdit::propertyInfo() const
+{
+ Q_D(const QFxTextEdit);
+ return QChar(QLatin1Char('\"')) + d->text + QChar(QLatin1Char('\"'));
+}
+
+/*!
+ Ensures any delayed caching or data loading the class
+ needs to performed is complete.
+*/
+void QFxTextEdit::componentComplete()
+{
+ Q_D(QFxTextEdit);
+ QFxPaintedItem::componentComplete();
+ if (d->dirty) {
+ updateSize();
+ d->dirty = false;
+ }
+}
+
+/*!
+ \qmlproperty bool TextEdit::readOnly
+
+ Whether the user an interact with the TextEdit item. If this
+ property is set to true the text cannot be edited by user interaction.
+
+ By default this property is false.
+*/
+
+/*!
+ \property QFxTextEdit::readOnly
+ \brief If this property is true the text can not be edited by user interaction.
+
+ Changing this property will modify the text interaction flags. If
+ you require more specific control about how user interaction
+ with the text edit is handled, use setTextInteractionFlags() instead.
+
+ \sa setTextInteractionFlags()
+*/
+void QFxTextEdit::setReadOnly(bool r)
+{
+ Q_D(QFxTextEdit);
+
+ Qt::TextInteractionFlags flags = Qt::NoTextInteraction;
+ if (r) {
+ flags = Qt::TextSelectableByMouse;
+ } else {
+ flags = Qt::TextEditorInteraction;
+ }
+ d->control->setTextInteractionFlags(flags);
+ if (!r)
+ d->control->moveCursor(QTextCursor::End);
+}
+
+bool QFxTextEdit::isReadOnly() const
+{
+ Q_D(const QFxTextEdit);
+ return !(d->control->textInteractionFlags() & Qt::TextEditable);
+}
+
+/*!
+ Sets how the text edit should interact with user input to the given
+ \a flags.
+*/
+void QFxTextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
+{
+ Q_D(QFxTextEdit);
+ d->control->setTextInteractionFlags(flags);
+}
+
+/*!
+ Returns the flags specifying how the text edit should interact
+ with user input.
+*/
+Qt::TextInteractionFlags QFxTextEdit::textInteractionFlags() const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->textInteractionFlags();
+}
+
+/*!
+ Returns the cursor for the point at the given \a pos on the
+ text edit.
+*/
+QTextCursor QFxTextEdit::cursorForPosition(const QPoint &pos) const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->cursorForPosition(pos);
+}
+
+/*!
+ Returns the rectangle where the given text \a cursor is rendered
+ within the text edit.
+*/
+QRect QFxTextEdit::cursorRect(const QTextCursor &cursor) const
+{
+ Q_D(const QFxTextEdit);
+ if (cursor.isNull())
+ return QRect();
+
+ return d->control->cursorRect(cursor).toRect();
+}
+
+/*!
+ Returns the rectangle where the text cursor is rendered
+ within the text edit.
+*/
+QRect QFxTextEdit::cursorRect() const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->cursorRect().toRect();
+}
+
+
+/*!
+ Sets the text cursor for the text edit to the given \a cursor.
+*/
+void QFxTextEdit::setTextCursor(const QTextCursor &cursor)
+{
+ Q_D(QFxTextEdit);
+ d->control->setTextCursor(cursor);
+}
+
+/*!
+ Returns the text cursor for the text edit.
+*/
+QTextCursor QFxTextEdit::textCursor() const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->textCursor();
+}
+
+/*!
+Moves the cursor by performing the given \a operation.
+
+If \a mode is QTextCursor::KeepAnchor, the cursor selects the text it moves over. This is the same effect that the user achieves when they hold down the Shift key and move the cursor with the cursor keys.
+*/
+void QFxTextEdit::moveCursor(QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode)
+{
+ Q_D(QFxTextEdit);
+ d->control->moveCursor(operation, mode);
+}
+
+/*!
+\overload
+Handles the given key \a event.
+*/
+void QFxTextEdit::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QFxTextEdit);
+ QTextCursor c = textCursor();
+ QTextCursor::MoveOperation op = QTextCursor::NoMove;
+ if (event == QKeySequence::MoveToNextChar) {
+ op = QTextCursor::Right;
+ } else if (event == QKeySequence::MoveToPreviousChar) {
+ op = QTextCursor::Left;
+ } else if (event == QKeySequence::MoveToNextWord) {
+ op = QTextCursor::WordRight;
+ } else if (event == QKeySequence::MoveToPreviousWord) {
+ op = QTextCursor::WordLeft;
+ } else if (event == QKeySequence::MoveToNextLine) {
+ op = QTextCursor::Down;
+ } else if (event == QKeySequence::MoveToPreviousLine) {
+ op = QTextCursor::Up;
+ }
+
+ if (op != QTextCursor::NoMove && !c.movePosition(op))
+ event->ignore();
+ else
+ d->control->processEvent(event, QPointF(0, 0));
+}
+
+/*!
+\overload
+Handles the given key \a event.
+*/
+void QFxTextEdit::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QFxTextEdit);
+ d->control->processEvent(event, QPointF(0, 0));
+}
+
+/*!
+ \overload
+ Handles changing of the focus property. Focus is applied to the control
+ even if the edit does not have active focus. This is because things
+ like KeyProxy can give the behavior of focus even when activeFocus isn't
+ true.
+*/
+void QFxTextEdit::focusChanged(bool hasFocus)
+{
+ Q_D(QFxTextEdit);
+ setCursorVisible(hasFocus);
+}
+
+/*!
+ Causes all text to be selected.
+*/
+void QFxTextEdit::selectAll()
+{
+ Q_D(QFxTextEdit);
+ d->control->selectAll();
+}
+
+static QMouseEvent *sceneMouseEventToMouseEvent(QGraphicsSceneMouseEvent *e)
+{
+ QEvent::Type t;
+ switch(e->type()) {
+ default:
+ case QEvent::GraphicsSceneMousePress:
+ t = QEvent::MouseButtonPress;
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ t = QEvent::MouseButtonRelease;
+ break;
+ case QEvent::GraphicsSceneMouseMove:
+ t = QEvent::MouseMove;
+ break;
+ case QGraphicsSceneEvent::GraphicsSceneMouseDoubleClick:
+ t = QEvent::MouseButtonDblClick;
+ break;
+ }
+
+ QMouseEvent *me = new QMouseEvent(t, e->pos().toPoint(), e->button(), e->buttons(), 0);
+ return me;
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QFxTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxTextEdit);
+ if (d->focusOnPress)
+ setFocus(true);
+ QMouseEvent *me = sceneMouseEventToMouseEvent(event);
+ d->control->processEvent(me, QPointF(0, 0));
+ event->setAccepted(me->isAccepted());
+ delete me;
+ if (!event->isAccepted())
+ QFxPaintedItem::mousePressEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QFxTextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxTextEdit);
+ QMouseEvent *me = sceneMouseEventToMouseEvent(event);
+ d->control->processEvent(me, QPointF(0, 0));
+ event->setAccepted(me->isAccepted());
+ delete me;
+ if (!event->isAccepted())
+ QFxPaintedItem::mousePressEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QFxTextEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxTextEdit);
+ QMouseEvent *me = sceneMouseEventToMouseEvent(event);
+ d->control->processEvent(me, QPointF(0, 0));
+ event->setAccepted(me->isAccepted());
+ delete me;
+ if (!event->isAccepted())
+ QFxPaintedItem::mousePressEvent(event);
+}
+
+/*!
+\overload
+Handles the given input method \a event.
+*/
+void QFxTextEdit::inputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QFxTextEdit);
+ d->control->processEvent(event, QPointF(0, 0));
+}
+
+/*!
+\overload
+Returns the value of the given \a property.
+*/
+QVariant QFxTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->inputMethodQuery(property);
+}
+
+/*!
+Draws the contents of the text edit using the given \a painter within
+the given \a bounds.
+*/
+void QFxTextEdit::drawContents(QPainter *painter, const QRect &bounds)
+{
+ Q_D(QFxTextEdit);
+
+ painter->setRenderHint(QPainter::TextAntialiasing, true);
+
+ d->control->drawContents(painter, bounds);
+}
+
+/*!
+This signal is emitted when the font of the item changes.
+*/
+void QFxTextEdit::fontChanged()
+{
+ Q_D(QFxTextEdit);
+ clearCache();
+ d->document->setDefaultFont(d->font.font());
+ updateSize();
+ emit update();
+}
+
+void QFxTextEdit::updateImgCache(const QRectF &r)
+{
+ dirtyCache(r.toRect());
+ emit update();
+}
+
+void QFxTextEditPrivate::init()
+{
+ Q_Q(QFxTextEdit);
+
+ q->setSmooth(true);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setOptions(QFxTextEdit::AcceptsInputMethods | QFxTextEdit::SimpleItem
+ | QFxTextEdit::HasContents | QFxTextEdit::MouseEvents);
+
+ QObject::connect(&font, SIGNAL(updated()), q, SLOT(fontChanged()));
+
+ control = new QTextControl(q);
+
+ QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateImgCache(QRectF)));
+
+ QObject::connect(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
+ QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
+
+ document = control->document();
+ document->setDefaultFont(font.font());
+ document->setDocumentMargin(0);
+ document->setUndoRedoEnabled(false); // flush undo buffer.
+ document->setUndoRedoEnabled(true);
+ updateDefaultTextOption();
+}
+
+void QFxTextEdit::q_textChanged()
+{
+ emit textChanged(text());
+}
+
+void QFxTextEdit::updateSize()
+{
+ Q_D(QFxTextEdit);
+ if (isComponentComplete()) {
+ QFontMetrics fm = QFontMetrics(d->font.font());
+ int dy = height();
+ // ### assumes that if the width is set, the text will fill to edges
+ // ### (unless wrap is false, then clipping will occur)
+ if (widthValid())
+ d->document->setTextWidth(width());
+ dy -= (int)d->document->size().height();
+
+ int yoff = 0;
+ if (heightValid()) {
+ if (d->vAlign == AlignBottom)
+ yoff = dy;
+ else if (d->vAlign == AlignVCenter)
+ yoff = dy/2;
+ }
+ setBaselineOffset(fm.ascent() + yoff);
+ if (!widthValid()) {
+ int newWidth = (int)d->document->idealWidth();
+ d->document->setTextWidth(newWidth); // ### QTextDoc> Alignment will not work unless textWidth is set
+ setImplicitWidth(newWidth);
+ }
+ if (!heightValid()) {
+ if (d->text.isEmpty()) {
+ setImplicitHeight(fm.height());
+ } else {
+ setImplicitHeight((int)d->document->size().height());
+ }
+ }
+ setContentsSize(QSize(width(), height()));
+ } else {
+ d->dirty = true;
+ }
+ emit update();
+}
+
+void QFxTextEditPrivate::updateDefaultTextOption()
+{
+ QTextOption opt = document->defaultTextOption();
+ int oldAlignment = opt.alignment();
+ opt.setAlignment((Qt::Alignment)(int)(hAlign | vAlign));
+
+ QTextOption::WrapMode oldWrapMode = opt.wrapMode();
+
+ if (wrap)
+ opt.setWrapMode(QTextOption::WordWrap);
+ else
+ opt.setWrapMode(QTextOption::NoWrap);
+
+ if (oldWrapMode == opt.wrapMode() && oldAlignment == opt.alignment())
+ return;
+ document->setDefaultTextOption(opt);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxtextedit.h b/src/declarative/fx/qfxtextedit.h
new file mode 100644
index 0000000..0aaa17b
--- /dev/null
+++ b/src/declarative/fx/qfxtextedit.h
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXTEXTEDIT_H
+#define QFXTEXTEDIT_H
+
+#include <qfxtext.h>
+#include <qfxpainteditem.h>
+
+#include <QtGui/qtextdocument.h>
+#include <QtGui/qtextoption.h>
+#include <QtGui/qtextcursor.h>
+#include <QtGui/qtextformat.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+/*!
+WARNING: SHORT TERM CLASS. INTENDED TO MERGE INTO QFxTextItem
+*/
+class QFxTextEditPrivate;
+class Q_DECLARATIVE_EXPORT QFxTextEdit : public QFxPaintedItem
+{
+ Q_OBJECT
+ Q_ENUMS(VAlignment)
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(TextFormat)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+ Q_PROPERTY(QColor highlightColor READ highlightColor WRITE setHighlightColor)
+ Q_PROPERTY(QmlFont * font READ font)
+ Q_PROPERTY(HAlignment hAlign READ hAlign WRITE setHAlign)
+ Q_PROPERTY(VAlignment vAlign READ vAlign WRITE setVAlign)
+ Q_PROPERTY(bool wrap READ wrap WRITE setWrap)
+ Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat)
+ Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)
+ Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible)
+ Q_PROPERTY(bool focusOnPress READ focusOnPress WRITE setFocusOnPress)
+ Q_CLASSINFO("DefaultProperty", "text")
+
+public:
+ QFxTextEdit(QFxItem *parent=0);
+
+ enum HAlignment {
+ AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter
+ };
+
+ enum VAlignment {
+ AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter
+ };
+
+ enum TextFormat {
+ AutoText,
+ PlainText,
+ RichText,
+ };
+
+ QString text() const;
+ void setText(const QString &);
+
+ TextFormat textFormat() const;
+ void setTextFormat(TextFormat format);
+
+ // leave in, have affect the default text
+ QmlFont *font();
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ QColor highlightColor() const;
+ void setHighlightColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+
+ VAlignment vAlign() const;
+ void setVAlign(VAlignment align);
+
+ bool wrap() const;
+ void setWrap(bool w);
+
+ bool isCursorVisible() const;
+ void setCursorVisible(bool on);
+
+ bool focusOnPress() const;
+ void setFocusOnPress(bool on);
+
+ virtual void dump(int depth);
+ virtual QString propertyInfo() const;
+
+ virtual void componentComplete();
+
+ /* FROM EDIT */
+ void setReadOnly(bool);
+ bool isReadOnly() const;
+
+ void setTextInteractionFlags(Qt::TextInteractionFlags flags);
+ Qt::TextInteractionFlags textInteractionFlags() const;
+
+ QTextCursor cursorForPosition(const QPoint &pos) const;
+ QRect cursorRect(const QTextCursor &cursor) const;
+ QRect cursorRect() const;
+
+ void setTextCursor(const QTextCursor &cursor);
+ QTextCursor textCursor() const;
+
+ void moveCursor(QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode = QTextCursor::MoveAnchor);
+
+ QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
+
+Q_SIGNALS:
+ void textChanged(const QString &);
+ void cursorPositionChanged();
+
+public Q_SLOTS:
+ void selectAll();
+
+private Q_SLOTS:
+ void fontChanged();
+ void updateImgCache(const QRectF &rect);
+ void q_textChanged();
+
+private:
+ void updateSize();
+
+protected:
+ QFxTextEdit(QFxTextEditPrivate &dd, QFxItem *parent);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+ void keyPressEvent(QKeyEvent *);
+ void keyReleaseEvent(QKeyEvent *);
+
+ void focusChanged(bool);
+
+ // mouse filter?
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+
+ void inputMethodEvent(QInputMethodEvent *e);
+
+ void drawContents(QPainter *, const QRect &);
+private:
+
+ friend class QmlFont;
+ Q_DISABLE_COPY(QFxTextEdit)
+ Q_DECLARE_PRIVATE(QFxTextEdit)
+};
+QML_DECLARE_TYPE(QFxTextEdit);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxtextedit_p.h b/src/declarative/fx/qfxtextedit_p.h
new file mode 100644
index 0000000..a9b7237
--- /dev/null
+++ b/src/declarative/fx/qfxtextedit_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXTEXTEDIT_P_H
+#define QFXTEXTEDIT_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 "qfxitem.h"
+#include "qfxpainteditem_p.h"
+#include "qml.h"
+
+
+QT_BEGIN_NAMESPACE
+class QTextLayout;
+class QTextDocument;
+class QTextControl;
+class QFxTextEditPrivate : public QFxPaintedItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxTextEdit)
+
+public:
+ QFxTextEditPrivate()
+ : font(0), color("black"), imgDirty(true), hAlign(QFxTextEdit::AlignLeft), vAlign(QFxTextEdit::AlignTop),
+ dirty(false), wrap(false), richText(false), cursorVisible(false), focusOnPress(false),
+ format(QFxTextEdit::AutoText), document(0)
+ {
+ }
+
+ void init();
+
+ void updateDefaultTextOption();
+ void relayoutDocument();
+
+ QString text;
+ QmlFont font;
+ QColor color;
+ QColor highlightColor;
+ QString style;
+ QColor styleColor;
+ bool imgDirty;
+#if defined(QFX_RENDER_OPENGL)
+ GLTexture texture;
+#endif
+ QSimpleCanvasConfig::Image imgCache;
+ QImage imgStyleCache;
+ QFxTextEdit::HAlignment hAlign;
+ QFxTextEdit::VAlignment vAlign;
+ bool dirty;
+ bool wrap;
+ bool richText;
+ bool cursorVisible;
+ bool focusOnPress;
+ QFxTextEdit::TextFormat format;
+ QTextDocument *document;
+ QTextControl *control;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/fx/qfxtransform.cpp b/src/declarative/fx/qfxtransform.cpp
new file mode 100644
index 0000000..289333c
--- /dev/null
+++ b/src/declarative/fx/qfxtransform.cpp
@@ -0,0 +1,865 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include "private/qfxitem_p.h"
+#include "qfxtransform.h"
+#include <QtDeclarative/qmlinfo.h>
+
+#include <math.h>
+#ifndef M_PI
+
+QT_BEGIN_NAMESPACE
+#define M_PI 3.14159265358979323846
+#endif
+
+QML_DEFINE_NOCREATE_TYPE(QFxTransform);
+
+/*!
+ \qmlclass Transform
+ \brief A transformation.
+*/
+QFxTransform::QFxTransform(QObject *parent) :
+ QObject(parent)
+{
+}
+
+QFxTransform::~QFxTransform()
+{
+}
+
+bool QFxTransform::isIdentity() const
+{
+ return true;
+}
+
+QSimpleCanvas::Matrix QFxTransform::transform() const
+{
+ return QSimpleCanvas::Matrix();
+}
+
+void QFxTransform::update()
+{
+ QFxItem *item = qobject_cast<QFxItem *>(parent());
+ if (item)
+ item->updateTransform();
+}
+
+/*!
+ \qmlclass Axis
+ \brief A Axis object defines an axis that can be used for rotation or translation.
+
+ An axis is specified by 2 points in 3D space: a start point and
+ an end point. While technically the axis is the line running through these two points
+ (and thus many different sets of two points could define the same axis), the distance
+ between the points does matter for translation along an axis.
+
+ \image 3d-axis.png
+
+ \qml
+ Axis { startX: 20; startY: 0; endX: 40; endY: 60; endZ: 20 }
+ \endqml
+*/
+
+QML_DEFINE_TYPE(QFxAxis, Axis);
+
+QFxAxis::QFxAxis(QObject *parent)
+: QObject(parent), _startX(0), _startY(0), _endX(0), _endY(0), _endZ(0)
+{
+}
+
+QFxAxis::~QFxAxis()
+{
+}
+
+/*!
+ \qmlproperty real Axis::startX
+ \qmlproperty real Axis::startY
+
+ The start point of the axis. The z-position of the start point is assumed to be 0, and cannot
+ be changed.
+*/
+qreal QFxAxis::startX() const
+{
+ return _startX;
+}
+
+void QFxAxis::setStartX(qreal x)
+{
+ _startX = x;
+ emit updated();
+}
+
+qreal QFxAxis::startY() const
+{
+ return _startY;
+}
+
+void QFxAxis::setStartY(qreal y)
+{
+ _startY = y;
+ emit updated();
+}
+
+/*!
+ \qmlproperty real Axis::endX
+ \qmlproperty real Axis::endY
+ \qmlproperty real Axis::endZ
+
+ The end point of the axis.
+*/
+qreal QFxAxis::endX() const
+{
+ return _endX;
+}
+
+void QFxAxis::setEndX(qreal x)
+{
+ _endX = x;
+ emit updated();
+}
+
+qreal QFxAxis::endY() const
+{
+ return _endY;
+}
+
+void QFxAxis::setEndY(qreal y)
+{
+ _endY = y;
+ emit updated();
+}
+
+qreal QFxAxis::endZ() const
+{
+ return _endZ;
+}
+
+void QFxAxis::setEndZ(qreal z)
+{
+ _endZ = z;
+ emit updated();
+}
+
+QFxRotation::QFxRotation(QObject *parent)
+: QFxTransform(parent), _originX(0), _originY(0), _angle(0), _dirty(true)
+{
+}
+
+QFxRotation::~QFxRotation()
+{
+}
+
+qreal QFxRotation::originX() const
+{
+ return _originX;
+}
+
+void QFxRotation::setOriginX(qreal ox)
+{
+ _originX = ox;
+ update();
+}
+
+qreal QFxRotation::originY() const
+{
+ return _originY;
+}
+
+void QFxRotation::setOriginY(qreal oy)
+{
+ _originY = oy;
+ update();
+}
+
+qreal QFxRotation::angle() const
+{
+ return _angle;
+}
+
+void QFxRotation::setAngle(qreal angle)
+{
+ _angle = angle;
+ update();
+}
+
+bool QFxRotation::isIdentity() const
+{
+ return (_angle == 0.);
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+QTransform QFxRotation::transform() const
+{
+ if (_dirty) {
+ _transform = QTransform();
+ _dirty = false;
+ _transform.translate(_originX, _originY);
+ _transform.rotate(_angle);
+ _transform.translate(-_originX, -_originY);
+ }
+ return _transform;
+}
+#elif defined(QFX_RENDER_OPENGL)
+QMatrix4x4 QFxRotation::transform() const
+{
+ if (_dirty) {
+ _transform = QMatrix4x4();
+ _dirty = false;
+ _transform.rotate(_angle, _originX, _originY);
+ }
+ return _transform;
+}
+#endif
+
+void QFxRotation::update()
+{
+ _dirty = true;
+ QFxTransform::update();
+}
+
+QML_DEFINE_TYPE(QFxRotation, Rotation);
+
+/*!
+ \qmlclass Rotation3D
+ \brief A Rotation3D object provides a way to rotate an Item around an axis.
+
+ Here is an example of various rotations applied to an \l Image.
+ \snippet doc/src/snippets/declarative/rotation.qml 0
+
+ \image axisrotation.png
+*/
+
+QML_DEFINE_TYPE(QFxRotation3D,Rotation3D);
+
+QFxRotation3D::QFxRotation3D(QObject *parent)
+: QFxTransform(parent), _angle(0), _dirty(true)
+{
+ connect(&_axis, SIGNAL(updated()), this, SLOT(update()));
+}
+
+QFxRotation3D::~QFxRotation3D()
+{
+}
+
+/*!
+ \qmlproperty real Rotation3D::axis.startX
+ \qmlproperty real Rotation3D::axis.startY
+ \qmlproperty real Rotation3D::axis.endX
+ \qmlproperty real Rotation3D::axis.endY
+ \qmlproperty real Rotation3D::axis.endZ
+
+ A rotation axis is specified by 2 points in 3D space: a start point and
+ an end point. The z-position of the start point is assumed to be 0, and cannot
+ be changed.
+
+ \image 3d-rotation-axis.png
+
+ \sa Axis
+*/
+QFxAxis *QFxRotation3D::axis()
+{
+ return &_axis;
+}
+
+/*!
+ \qmlproperty real Rotation3D::angle
+
+ The angle, in degrees, to rotate around the specified axis.
+*/
+qreal QFxRotation3D::angle() const
+{
+ return _angle;
+}
+
+void QFxRotation3D::setAngle(qreal angle)
+{
+ _angle = angle;
+ update();
+}
+
+bool QFxRotation3D::isIdentity() const
+{
+ return (_angle == 0.) || (_axis.endZ() == 0. && _axis.endY() == _axis.startY() && _axis.endX() == _axis.startX());
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+const qreal inv_dist_to_plane = 1. / 1024.;
+QTransform QFxRotation3D::transform() const
+{
+ if (_dirty) {
+ _transform = QTransform();
+
+ if (!isIdentity()) {
+ if (angle() != 0.) {
+ QTransform rotTrans;
+ rotTrans.translate(-_axis.startX(), -_axis.startY());
+ QTransform rotTrans2;
+ rotTrans2.translate(_axis.startX(), _axis.startY());
+
+ qreal rad = angle() * 2. * M_PI / 360.;
+ qreal c = ::cos(rad);
+ qreal s = ::sin(rad);
+
+ qreal x = _axis.endX() - _axis.startX();
+ qreal y = _axis.endY() - _axis.startY();
+ qreal z = _axis.endZ();
+
+ qreal len = x * x + y * y + z * z;
+ if (len != 1.) {
+ len = ::sqrt(len);
+ x /= len;
+ y /= len;
+ z /= len;
+ }
+
+ QTransform rot(x*x*(1-c)+c, x*y*(1-c)-z*s, x*z*(1-c)+y*s*inv_dist_to_plane,
+ y*x*(1-c)+z*s, y*y*(1-c)+c, y*z*(1-c)-x*s*inv_dist_to_plane,
+ 0, 0, 1);
+
+ _transform *= rotTrans;
+ _transform *= rot;
+ _transform *= rotTrans2;
+ }
+ }
+
+ _dirty = false;
+ }
+
+ return _transform;
+}
+#elif defined(QFX_RENDER_OPENGL)
+QMatrix4x4 QFxRotation3D::transform() const
+{
+ if (_dirty) {
+ _dirty = false;
+ _transform = QMatrix4x4();
+
+ if (!isIdentity()) {
+ if (angle() != 0.) {
+ qreal x = _axis.endX() - _axis.startX();
+ qreal y = _axis.endY() - _axis.startY();
+ qreal z = _axis.endZ();
+
+ _transform.translate(_axis.startX(), _axis.startY(), 0);
+ _transform.rotate(angle(), x, y, z);
+ _transform.translate(-_axis.startX(), -_axis.startY(), 0);
+ }
+ }
+ }
+
+ return _transform;
+}
+#endif
+
+void QFxRotation3D::update()
+{
+ _dirty = true;
+ QFxTransform::update();
+}
+
+/*!
+ \internal
+ \qmlclass Translation3D
+ \brief A Translation3D object provides a way to move an Item along an axis.
+
+ The following example translates the image to 10, 3.
+ \qml
+Image {
+ source: "logo.png"
+ transform: [
+ Translation3D {
+ axis.startX: 0
+ axis.startY: 0
+ axis.endX: 1
+ axis.endY: .3
+ distance: 10
+ }
+ ]
+}
+ \endqml
+*/
+
+QML_DEFINE_TYPE(QFxTranslation3D,Translation3D);
+
+QFxTranslation3D::QFxTranslation3D(QObject *parent)
+: QFxTransform(parent), _distance(0), _dirty(true)
+{
+ connect(&_axis, SIGNAL(updated()), this, SLOT(update()));
+}
+
+QFxTranslation3D::~QFxTranslation3D()
+{
+}
+
+/*!
+ \qmlproperty real Translation3D::axis.startX
+ \qmlproperty real Translation3D::axis.startY
+ \qmlproperty real Translation3D::axis.endX
+ \qmlproperty real Translation3D::axis.endY
+ \qmlproperty real Translation3D::axis.endZ
+
+ A translation axis is specified by 2 points in 3D space: a start point and
+ an end point. The z-position of the start point is assumed to be 0, and cannot
+ be changed. Changing the z-position of the end point is only valid when running
+ under OpenGL.
+
+ \sa Axis
+*/
+QFxAxis *QFxTranslation3D::axis()
+{
+ return &_axis;
+}
+
+/*!
+ \qmlproperty real Translation3D::distance
+
+ The distance to translate along the specified axis. distance is a multiplier;
+ in the example below, a distance of 1 would translate to 100, 50, while a distance
+ of 0.5 would translate to 50, 25.
+
+ \qml
+ Translation3D { axis.startX: 0; axis.startY: 0; axis.endX: 100; axis.endY: 50 }
+ \endqml
+*/
+qreal QFxTranslation3D::distance() const
+{
+ return _distance;
+}
+
+void QFxTranslation3D::setDistance(qreal distance)
+{
+ _distance = distance;
+ update();
+}
+
+bool QFxTranslation3D::isIdentity() const
+{
+ return (_distance == 0.) || (_axis.endZ() == 0. && _axis.endY() == _axis.startY() && _axis.endX() == _axis.startX());
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+QTransform QFxTranslation3D::transform() const
+{
+ if (_dirty) {
+ _transform = QTransform();
+
+ if (!isIdentity()) {
+ if (distance() != 0.) {
+ QTransform trans;
+ trans.translate((_axis.endX() - _axis.startX()) * distance(),
+ (_axis.endY() - _axis.startY()) * distance());
+ _transform *= trans;
+ }
+ }
+
+ _dirty = false;
+ }
+
+ return _transform;
+}
+#elif defined(QFX_RENDER_OPENGL)
+QMatrix4x4 QFxTranslation3D::transform() const
+{
+ if (_dirty) {
+ _dirty = false;
+ _transform = QMatrix4x4();
+
+ if (!isIdentity()) {
+ if (distance() != 0.)
+ _transform.translate((_axis.endX() - _axis.startX()) * distance(),
+ (_axis.endY() - _axis.startY()) * distance(),
+ (_axis.endZ()) * distance());
+
+ }
+ }
+
+ return _transform;
+}
+#endif
+
+void QFxTranslation3D::update()
+{
+ _dirty = true;
+
+#if !defined(QFX_RENDER_OPENGL)
+ if (_axis.endZ() != 0. && distance() != 0.) {
+ qmlInfo(this) << "QTransform cannot translate along Z-axis.";
+ }
+#endif
+
+ QFxTransform::update();
+}
+
+/*!
+ \internal
+ \qmlclass Perspective
+ \brief A Perspective object specifies a perspective transformation.
+
+ A Perspective transform only affects an item when running under OpenGL; when running under software
+ rasterization it has no effect.
+*/
+
+QML_DEFINE_TYPE(QFxPerspective,Perspective);
+
+QFxPerspective::QFxPerspective(QObject *parent)
+ : QFxTransform(parent)
+{
+}
+
+QFxPerspective::~QFxPerspective()
+{
+}
+
+#if defined(QFX_RENDER_OPENGL)
+bool QFxPerspective::isIdentity() const
+{
+ return false;
+}
+
+QMatrix4x4 QFxPerspective::transform() const
+{
+ QMatrix4x4 rv;
+ rv.translate(_x, _y);
+ rv.perspective(_angle, _aspect, 1, 1024 * 1024);
+ rv.translate(-_x, -_y, -1);
+ rv.scale(1, 1, 1. / _scale);
+
+ return rv;
+}
+#endif
+
+/*!
+ \qmlproperty real Perspective::angle
+*/
+
+/*!
+ \qmlproperty real Perspective::aspect
+*/
+
+/*!
+ \qmlproperty real Perspective::x
+*/
+
+/*!
+ \qmlproperty real Perspective::y
+*/
+
+/*!
+ \qmlproperty real Perspective::scale
+*/
+
+/*!
+ \qmlclass Squish
+ \brief A Squish object allows you to distort an item's appearance by 'squishing' it.
+
+ Conceptually, a Squish works by allowing you to move the four corners of an item,
+ and distorting the item to fit into the newly created polygon.
+
+ \image squish-transform.png
+
+ Here is an example of various \l Image squishes.
+ \qml
+ Rect {
+ id: Screen
+ width: 360; height: 80
+ color: "white"
+
+ HorizontalLayout {
+ margin: 10
+ spacing: 10
+ Image { source: "qt.png" }
+ Image {
+ source: "qt.png"
+ transform: Squish {
+ x:0; y:0; width:60; height:60
+ topLeftX:0; topLeftY:0
+ topRightX:50; topRightY:10
+ bottomLeftX:0; bottomLeftY:60
+ bottomRightX: 60; bottomRightY:60
+ }
+ }
+ Image {
+ source: "qt.png"
+ transform: Squish {
+ x:0; y:0; width:60; height:60
+ topLeftX:0; topLeftY:0
+ topRightX:50; topRightY:0
+ bottomLeftX:10; bottomLeftY:50
+ bottomRightX: 60; bottomRightY:60
+ }
+ }
+ Image {
+ source: "qt.png"
+ transform: Squish {
+ x:0; y:0; width:60; height:60
+ topLeftX:0; topLeftY:10
+ topRightX:60; topRightY:10
+ bottomLeftX:0; bottomLeftY:50
+ bottomRightX: 60; bottomRightY:50
+ }
+ }
+ Image {
+ source: "qt.png"
+ transform: Squish {
+ x:0; y:0; width:60; height:60
+ topLeftX:10; topLeftY:0
+ topRightX:50; topRightY:0
+ bottomLeftX:10; bottomLeftY:60
+ bottomRightX: 50; bottomRightY:60
+ }
+ }
+ }
+ }
+ \endqml
+
+ \image squish.png
+*/
+QML_DEFINE_TYPE(QFxSquish,Squish);
+
+QFxSquish::QFxSquish(QObject *parent)
+ : QFxTransform(parent)
+{
+}
+
+QFxSquish::~QFxSquish()
+{
+}
+
+/*!
+ \qmlproperty real Squish::x
+ \qmlproperty real Squish::y
+ \qmlproperty real Squish::width
+ \qmlproperty real Squish::height
+
+ This is usually set to the original geometry of the item being squished.
+*/
+qreal QFxSquish::x() const
+{
+ return p.x();
+}
+
+void QFxSquish::setX(qreal v)
+{
+ p.setX(v);
+ update();
+}
+
+qreal QFxSquish::y() const
+{
+ return p.y();
+}
+
+void QFxSquish::setY(qreal v)
+{
+ p.setY(v);
+ update();
+}
+
+qreal QFxSquish::width() const
+{
+ return s.width();
+}
+
+void QFxSquish::setWidth(qreal v)
+{
+ s.setWidth(v);
+ update();
+}
+
+qreal QFxSquish::height() const
+{
+ return s.height();
+}
+
+void QFxSquish::setHeight(qreal v)
+{
+ s.setHeight(v);
+ update();
+}
+
+/*!
+ \qmlproperty real Squish::topLeftX
+ \qmlproperty real Squish::topLeftY
+
+ The top left point for the squish.
+*/
+qreal QFxSquish::topLeft_x() const
+{
+ return p1.x();
+}
+
+void QFxSquish::settopLeft_x(qreal v)
+{
+ p1.setX(v);
+ update();
+}
+
+qreal QFxSquish::topLeft_y() const
+{
+ return p1.y();
+}
+
+void QFxSquish::settopLeft_y(qreal v)
+{
+ p1.setY(v);
+ update();
+}
+
+/*!
+ \qmlproperty real Squish::topRightX
+ \qmlproperty real Squish::topRightY
+
+ The top right point for the squish.
+*/
+qreal QFxSquish::topRight_x() const
+{
+ return p2.x();
+}
+
+void QFxSquish::settopRight_x(qreal v)
+{
+ p2.setX(v);
+ update();
+}
+
+qreal QFxSquish::topRight_y() const
+{
+ return p2.y();
+}
+
+void QFxSquish::settopRight_y(qreal v)
+{
+ p2.setY(v);
+ update();
+}
+
+/*!
+ \qmlproperty real Squish::bottomLeftX
+ \qmlproperty real Squish::bottomLeftY
+
+ The bottom left point for the squish.
+*/
+qreal QFxSquish::bottomLeft_x() const
+{
+ return p3.x();
+}
+
+void QFxSquish::setbottomLeft_x(qreal v)
+{
+ p3.setX(v);
+ update();
+}
+
+qreal QFxSquish::bottomLeft_y() const
+{
+ return p3.y();
+}
+
+void QFxSquish::setbottomLeft_y(qreal v)
+{
+ p3.setY(v);
+ update();
+}
+
+/*!
+ \qmlproperty real Squish::bottomRightX
+ \qmlproperty real Squish::bottomRightY
+
+ The bottom right point for the squish.
+*/
+qreal QFxSquish::bottomRight_x() const
+{
+ return p4.x();
+}
+
+void QFxSquish::setbottomRight_x(qreal v)
+{
+ p4.setX(v);
+ update();
+}
+
+qreal QFxSquish::bottomRight_y() const
+{
+ return p4.y();
+}
+
+void QFxSquish::setbottomRight_y(qreal v)
+{
+ p4.setY(v);
+ update();
+}
+
+bool QFxSquish::isIdentity() const
+{
+ return false;
+}
+
+#if defined(QFX_RENDER_QPAINTER)
+QTransform QFxSquish::transform() const
+{
+ QPolygonF poly;
+ poly << p << QPointF(p.x() + s.width(), p.y()) << QPointF(p.x() + s.width(), p.y() + s.height()) << QPointF(p.x(), p.y() + s.height());
+ QPolygonF poly2;
+ poly2 << p1 << p2 << p4 << p3;
+
+ QTransform t;
+ QTransform::quadToQuad(poly, poly2, t);
+ return t;
+}
+#elif defined(QFX_RENDER_OPENGL)
+QMatrix4x4 QFxSquish::transform() const
+{
+ QPolygonF poly;
+ poly << p << QPointF(p.x() + s.width(), p.y()) << QPointF(p.x() + s.width(), p.y() + s.height()) << QPointF(p.x(), p.y() + s.height());
+ QPolygonF poly2;
+ poly2 << p1 << p2 << p4 << p3;
+
+ QTransform t;
+ QMatrix4x4 rv;
+ if (QTransform::quadToQuad(poly, poly2, t))
+ rv = QMatrix4x4(t);
+
+ return rv;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxtransform.h b/src/declarative/fx/qfxtransform.h
new file mode 100644
index 0000000..a3a1a83
--- /dev/null
+++ b/src/declarative/fx/qfxtransform.h
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXTRANSFORM_H
+#define QFXTRANSFORM_H
+
+#include <QObject>
+#include <QTransform>
+#if defined(QFX_RENDER_OPENGL)
+#include <QtGui/qmatrix4x4.h>
+#endif
+#include <qfxitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QFxTransform : public QObject
+{
+ Q_OBJECT
+public:
+ QFxTransform(QObject *parent=0);
+ ~QFxTransform();
+
+ void update();
+
+ virtual bool isIdentity() const;
+ virtual QSimpleCanvas::Matrix transform() const;
+};
+QML_DECLARE_TYPE(QFxTransform);
+
+class Q_DECLARATIVE_EXPORT QFxAxis : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal startX READ startX WRITE setStartX)
+ Q_PROPERTY(qreal startY READ startY WRITE setStartY)
+ Q_PROPERTY(qreal endX READ endX WRITE setEndX)
+ Q_PROPERTY(qreal endY READ endY WRITE setEndY)
+ Q_PROPERTY(qreal endZ READ endZ WRITE setEndZ)
+public:
+ QFxAxis(QObject *parent=0);
+ ~QFxAxis();
+
+ qreal startX() const;
+ void setStartX(qreal);
+
+ qreal startY() const;
+ void setStartY(qreal);
+
+ qreal endX() const;
+ void setEndX(qreal);
+
+ qreal endY() const;
+ void setEndY(qreal);
+
+ qreal endZ() const;
+ void setEndZ(qreal);
+
+Q_SIGNALS:
+ void updated();
+
+private:
+ qreal _startX;
+ qreal _startY;
+ qreal _endX;
+ qreal _endY;
+ qreal _endZ;
+};
+QML_DECLARE_TYPE(QFxAxis);
+
+class Q_DECLARATIVE_EXPORT QFxRotation : public QFxTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal originX READ originX WRITE setOriginX)
+ Q_PROPERTY(qreal originY READ originY WRITE setOriginY)
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle)
+public:
+ QFxRotation(QObject *parent=0);
+ ~QFxRotation();
+
+ qreal originX() const;
+ void setOriginX(qreal);
+
+ qreal originY() const;
+ void setOriginY(qreal);
+
+ qreal angle() const;
+ void setAngle(qreal);
+
+ virtual bool isIdentity() const;
+ virtual QSimpleCanvas::Matrix transform() const;
+
+private Q_SLOTS:
+ void update();
+private:
+ qreal _originX;
+ qreal _originY;
+ qreal _angle;
+
+ mutable bool _dirty;
+ mutable QSimpleCanvas::Matrix _transform;
+};
+QML_DECLARE_TYPE(QFxRotation);
+
+class Q_DECLARATIVE_EXPORT QFxRotation3D : public QFxTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QFxAxis *axis READ axis)
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle)
+public:
+ QFxRotation3D(QObject *parent=0);
+ ~QFxRotation3D();
+
+ QFxAxis *axis();
+
+ qreal angle() const;
+ void setAngle(qreal);
+
+ virtual bool isIdentity() const;
+ virtual QSimpleCanvas::Matrix transform() const;
+
+private Q_SLOTS:
+ void update();
+private:
+ QFxAxis _axis;
+ qreal _angle;
+
+ mutable bool _dirty;
+ mutable QSimpleCanvas::Matrix _transform;
+};
+QML_DECLARE_TYPE(QFxRotation3D);
+
+class Q_DECLARATIVE_EXPORT QFxTranslation3D : public QFxTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QFxAxis *axis READ axis)
+ Q_PROPERTY(qreal distance READ distance WRITE setDistance)
+public:
+ QFxTranslation3D(QObject *parent=0);
+ ~QFxTranslation3D();
+
+ QFxAxis *axis();
+
+ qreal distance() const;
+ void setDistance(qreal);
+
+ virtual bool isIdentity() const;
+ virtual QSimpleCanvas::Matrix transform() const;
+
+private Q_SLOTS:
+ void update();
+private:
+ QFxAxis _axis;
+ qreal _distance;
+
+ mutable bool _dirty;
+ mutable QSimpleCanvas::Matrix _transform;
+};
+QML_DECLARE_TYPE(QFxTranslation3D);
+
+class Q_DECLARATIVE_EXPORT QFxPerspective : public QFxTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle)
+ Q_PROPERTY(qreal aspect READ aspect WRITE setAspect)
+ Q_PROPERTY(qreal x READ x WRITE setX)
+ Q_PROPERTY(qreal y READ y WRITE setY)
+ Q_PROPERTY(qreal scale READ scale WRITE setScale)
+public:
+ QFxPerspective(QObject *parent=0);
+ ~QFxPerspective();
+
+ qreal angle() const { return _angle; }
+ void setAngle(qreal v) { _angle = v; update(); }
+
+ qreal aspect() const { return _aspect; }
+ void setAspect(qreal v) { _aspect = v; update(); }
+
+ qreal x() const { return _x; }
+ void setX(qreal v) { _x = v; update(); }
+
+ qreal y() const { return _y; }
+ void setY(qreal v) { _y = v; update(); }
+
+ qreal scale() const { return _scale; }
+ void setScale(qreal v) { _scale = v; update(); }
+
+#if defined(QFX_RENDER_OPENGL)
+ virtual bool isIdentity() const;
+ virtual QMatrix4x4 transform() const;
+#endif
+private:
+ qreal _scale;
+ qreal _x;
+ qreal _y;
+ qreal _angle;
+ qreal _aspect;
+};
+QML_DECLARE_TYPE(QFxPerspective);
+
+class Q_DECLARATIVE_EXPORT QFxSquish : public QFxTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal x READ x WRITE setX)
+ Q_PROPERTY(qreal y READ y WRITE setY)
+ Q_PROPERTY(qreal width READ width WRITE setWidth)
+ Q_PROPERTY(qreal height READ height WRITE setHeight)
+ Q_PROPERTY(qreal topLeftX READ topLeft_x WRITE settopLeft_x)
+ Q_PROPERTY(qreal topLeftY READ topLeft_y WRITE settopLeft_y)
+ Q_PROPERTY(qreal topRightX READ topRight_x WRITE settopRight_x)
+ Q_PROPERTY(qreal topRightY READ topRight_y WRITE settopRight_y)
+ Q_PROPERTY(qreal bottomLeftX READ bottomLeft_x WRITE setbottomLeft_x)
+ Q_PROPERTY(qreal bottomLeftY READ bottomLeft_y WRITE setbottomLeft_y)
+ Q_PROPERTY(qreal bottomRightX READ bottomRight_x WRITE setbottomRight_x)
+ Q_PROPERTY(qreal bottomRightY READ bottomRight_y WRITE setbottomRight_y)
+public:
+ QFxSquish(QObject *parent=0);
+ ~QFxSquish();
+
+ qreal x() const;
+ void setX(qreal);
+
+ qreal y() const;
+ void setY(qreal);
+
+ qreal width() const;
+ void setWidth(qreal);
+
+ qreal height() const;
+ void setHeight(qreal);
+
+ qreal topLeft_x() const;
+ void settopLeft_x(qreal);
+
+ qreal topLeft_y() const;
+ void settopLeft_y(qreal);
+
+ qreal topRight_x() const;
+ void settopRight_x(qreal);
+
+ qreal topRight_y() const;
+ void settopRight_y(qreal);
+
+ qreal bottomLeft_x() const;
+ void setbottomLeft_x(qreal);
+
+ qreal bottomLeft_y() const;
+ void setbottomLeft_y(qreal);
+
+ qreal bottomRight_y() const;
+ void setbottomRight_y(qreal);
+
+ qreal bottomRight_x() const;
+ void setbottomRight_x(qreal);
+
+ virtual bool isIdentity() const;
+ virtual QSimpleCanvas::Matrix transform() const;
+
+private:
+ QPointF p;
+ QSizeF s;
+ QPointF p1, p2, p3, p4;
+};
+QML_DECLARE_TYPE(QFxSquish);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXTRANSFORM_H
diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp
new file mode 100644
index 0000000..533917e
--- /dev/null
+++ b/src/declarative/fx/qfxvisualitemmodel.cpp
@@ -0,0 +1,726 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlistmodelinterface.h"
+#include "qfxitem.h"
+#include <qmlcontext.h>
+#include <qmlexpression.h>
+#include "qmlpackage.h"
+#include "qhash.h"
+#include "qlist.h"
+#include "private/qobject_p.h"
+#include "private/qmetaobjectbuilder_p.h"
+#include "qmlopenmetaobject.h"
+#include "qmllistaccessor.h"
+#include "qfxvisualitemmodel.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DECLARE_TYPE(QListModelInterface);
+
+class QFxVisualItemModelParts;
+class QFxVisualItemModelData;
+class QFxVisualItemModelPrivate : public QObjectPrivate
+{
+public:
+ QFxVisualItemModelPrivate(QmlContext *);
+
+ QListModelInterface *m_listModelInterface;
+ QAbstractItemModel *m_abstractItemModel;
+ QFxVisualItemModel *m_visualItemModel;
+ QString m_part;
+
+ QmlComponent *m_delegate;
+ QmlContext *m_context;
+ QList<int> m_roles;
+ QHash<int,QString> m_roleNames;
+
+ QHash<int, QObject *> m_cache;
+ QHash<QObject *, QmlPackage*> m_packaged;
+ QHash<QmlPackage*, int> m_packageRef;
+
+ QFxVisualItemModelParts *m_parts;
+ friend class QFxVisualItemParts;
+
+ QFxVisualItemModelData *data(QObject *item);
+
+ QVariant m_modelVariant;
+ QmlListAccessor *m_modelList;
+
+ int modelCount() const {
+ if (m_visualItemModel)
+ return m_visualItemModel->count();
+ if (m_listModelInterface)
+ return m_listModelInterface->count();
+ if (m_abstractItemModel)
+ return m_abstractItemModel->rowCount();
+ if (m_modelList)
+ return m_modelList->count();
+ return 0;
+ }
+};
+
+class QFxVisualItemModelDataMetaObject : public QmlOpenMetaObject
+{
+public:
+ QFxVisualItemModelDataMetaObject(QObject *parent)
+ : QmlOpenMetaObject(parent) {}
+
+ virtual QVariant propertyCreated(int, QMetaPropertyBuilder &);
+ virtual int createProperty(const char *, const char *);
+
+private:
+ friend class QFxVisualItemModelData;
+ QList<int> roles;
+};
+
+class QFxVisualItemModelData : public QObject
+{
+Q_OBJECT
+public:
+ QFxVisualItemModelData(int index, QFxVisualItemModelPrivate *model);
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged);
+ int index() const;
+ void setIndex(int index);
+
+ int count() const;
+ int role(int) const;
+ void setValue(int, const QVariant &);
+
+Q_SIGNALS:
+ void indexChanged();
+
+private:
+ friend class QFxVisualItemModelDataMetaObject;
+ int m_index;
+ QFxVisualItemModelPrivate *m_model;
+ QFxVisualItemModelDataMetaObject *m_meta;
+};
+
+int QFxVisualItemModelData::count() const
+{
+ return m_meta->count();
+}
+
+int QFxVisualItemModelData::role(int id) const
+{
+ Q_ASSERT(id >= 0 && id < count());
+ return m_meta->roles.at(id);
+}
+
+void QFxVisualItemModelData::setValue(int id, const QVariant &val)
+{
+ m_meta->setValue(id, val);
+}
+
+int QFxVisualItemModelDataMetaObject::createProperty(const char *name, const char *type)
+{
+ QFxVisualItemModelData *data =
+ static_cast<QFxVisualItemModelData *>(object());
+
+ if ((!data->m_model->m_listModelInterface || !data->m_model->m_abstractItemModel)
+ && data->m_model->m_modelList) {
+ if (!qstrcmp(name, "modelData"))
+ return QmlOpenMetaObject::createProperty(name, type);
+ } else {
+ const QLatin1String sname(name);
+ for (QHash<int, QString>::ConstIterator iter = data->m_model->m_roleNames.begin();
+ iter != data->m_model->m_roleNames.end(); ++iter) {
+
+ if (*iter == sname)
+ return QmlOpenMetaObject::createProperty(name, type);
+ }
+ }
+ return -1;
+}
+
+QVariant
+QFxVisualItemModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
+{
+ prop.setWritable(false);
+
+ QFxVisualItemModelData *data =
+ static_cast<QFxVisualItemModelData *>(object());
+ QString name = QLatin1String(prop.name());
+ if ((!data->m_model->m_listModelInterface || !data->m_model->m_abstractItemModel)
+ && data->m_model->m_modelList) {
+ return data->m_model->m_modelList->at(data->m_index);
+ } else if (data->m_model->m_listModelInterface) {
+ for (QHash<int, QString>::ConstIterator iter = data->m_model->m_roleNames.begin();
+ iter != data->m_model->m_roleNames.end(); ++iter) {
+
+ if (*iter == name) {
+ roles.append(iter.key());
+ QHash<int,QVariant> values = data->m_model->m_listModelInterface->data(data->m_index, QList<int>() << iter.key());
+ if (values.isEmpty())
+ return QVariant();
+ else
+ return *values.begin();
+ }
+ }
+ } else if (data->m_model->m_abstractItemModel) {
+ for (QHash<int, QString>::ConstIterator iter = data->m_model->m_roleNames.begin();
+ iter != data->m_model->m_roleNames.end(); ++iter) {
+
+ if (*iter == name) {
+ roles.append(iter.key());
+ QModelIndex index = data->m_model->m_abstractItemModel->index(data->m_index, 0);
+ return data->m_model->m_abstractItemModel->data(index, iter.key());
+ }
+ }
+ }
+ Q_ASSERT(!"Can never be reached");
+ return QVariant();
+}
+
+QFxVisualItemModelData::QFxVisualItemModelData(int index,
+ QFxVisualItemModelPrivate *model)
+: m_index(index), m_model(model),
+ m_meta(new QFxVisualItemModelDataMetaObject(this))
+{
+}
+
+int QFxVisualItemModelData::index() const
+{
+ return m_index;
+}
+
+// This is internal only - it should not be set from qml
+void QFxVisualItemModelData::setIndex(int index)
+{
+ m_index = index;
+ emit indexChanged();
+}
+
+class QFxVisualItemModelPartsMetaObject : public QmlOpenMetaObject
+{
+public:
+ QFxVisualItemModelPartsMetaObject(QObject *parent)
+ : QmlOpenMetaObject(parent) {}
+
+ virtual QVariant propertyCreated(int, QMetaPropertyBuilder &);
+};
+
+class QFxVisualItemModelParts : public QObject
+{
+Q_OBJECT
+public:
+ QFxVisualItemModelParts(QFxVisualItemModel *parent);
+
+private:
+ friend class QFxVisualItemModelPartsMetaObject;
+ QFxVisualItemModel *model;
+};
+
+QVariant
+QFxVisualItemModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
+{
+ prop.setWritable(false);
+
+ QFxVisualItemModel *m = new QFxVisualItemModel;
+ m->setParent(object());
+ m->setPart(QLatin1String(prop.name()));
+ m->setModel(QVariant::fromValue(static_cast<QFxVisualItemModelParts *>(object())->model));
+
+ QVariant var = QVariant::fromValue((QObject *)m);
+ return var;
+}
+
+QFxVisualItemModelParts::QFxVisualItemModelParts(QFxVisualItemModel *parent)
+: QObject(parent), model(parent)
+{
+ new QFxVisualItemModelPartsMetaObject(this);
+}
+
+QFxVisualItemModelPrivate::QFxVisualItemModelPrivate(QmlContext *ctxt)
+: m_listModelInterface(0), m_abstractItemModel(0), m_visualItemModel(0), m_delegate(0)
+, m_context(ctxt), m_parts(0), m_modelList(0)
+{
+}
+
+QFxVisualItemModelData *QFxVisualItemModelPrivate::data(QObject *item)
+{
+ QList<QFxVisualItemModelData *> dataList =
+ item->findChildren<QFxVisualItemModelData *>();
+ Q_ASSERT(dataList.count() == 1);
+ return dataList.first();
+}
+
+QFxVisualItemModel::QFxVisualItemModel()
+: QObject(*(new QFxVisualItemModelPrivate(0)))
+{
+}
+
+QFxVisualItemModel::QFxVisualItemModel(QmlContext *ctxt)
+: QObject(*(new QFxVisualItemModelPrivate(ctxt)))
+{
+}
+
+QFxVisualItemModel::~QFxVisualItemModel()
+{
+ Q_D(QFxVisualItemModel);
+ if (d->m_modelList)
+ delete d->m_modelList;
+}
+
+QVariant QFxVisualItemModel::model() const
+{
+ Q_D(const QFxVisualItemModel);
+ return d->m_modelVariant;
+}
+
+void QFxVisualItemModel::setModel(const QVariant &model)
+{
+ Q_D(QFxVisualItemModel);
+ d->m_modelVariant = model;
+ if (d->m_listModelInterface) {
+ // Assume caller has released all items.
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
+ this, SLOT(_q_itemsChanged(int,int,QList<int>)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
+ this, SLOT(_q_itemsInserted(int,int)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
+ this, SLOT(_q_itemsRemoved(int,int)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
+ this, SLOT(_q_itemsMoved(int,int,int)));
+ d->m_listModelInterface = 0;
+ } else if (d->m_abstractItemModel) {
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsInserted(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsInserted(const QModelIndex &,int,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsRemoved(const QModelIndex &,int,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
+ this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
+ } else if (d->m_visualItemModel) {
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
+ this, SIGNAL(itemsInserted(int,int)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
+ this, SIGNAL(itemsRemoved(int,int)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
+ this, SIGNAL(itemsMoved(int,int,int)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(packageCreated(int,QmlPackage*)),
+ this, SLOT(_q_packageCreated(int,QmlPackage*)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(destroyingPackage(QmlPackage*)),
+ this, SLOT(_q_destroyingPackage(QmlPackage*)));
+ d->m_visualItemModel = 0;
+ }
+
+ QObject *object = qvariant_cast<QObject *>(model);
+ if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
+ d->m_roles.clear();
+ d->m_roleNames.clear();
+ if (d->m_listModelInterface) {
+ d->m_roles = d->m_listModelInterface->roles();
+ for (int ii = 0; ii < d->m_roles.count(); ++ii)
+ d->m_roleNames.insert(d->m_roles.at(ii),
+ d->m_listModelInterface->toString(d->m_roles.at(ii)));
+ }
+
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
+ this, SLOT(_q_itemsChanged(int,int,QList<int>)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
+ this, SLOT(_q_itemsInserted(int,int)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
+ this, SLOT(_q_itemsRemoved(int,int)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
+ this, SLOT(_q_itemsMoved(int,int,int)));
+
+ if (d->m_delegate && d->m_listModelInterface->count())
+ emit itemsInserted(0, d->m_listModelInterface->count());
+ return;
+ } else if (object && (d->m_abstractItemModel = qobject_cast<QAbstractItemModel *>(object))) {
+ d->m_roles.clear();
+ d->m_roleNames.clear();
+ for (QHash<int,QByteArray>::const_iterator it = d->m_abstractItemModel->roleNames().begin();
+ it != d->m_abstractItemModel->roleNames().end(); ++it) {
+ d->m_roles.append(it.key());
+ d->m_roleNames.insert(it.key(), QLatin1String(*it));
+ }
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsInserted(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsInserted(const QModelIndex &,int,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsRemoved(const QModelIndex &,int,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
+ this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
+ return;
+ }
+ if ((d->m_visualItemModel = qvariant_cast<QFxVisualItemModel *>(model))) {
+ QObject::connect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
+ this, SIGNAL(itemsInserted(int,int)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
+ this, SIGNAL(itemsRemoved(int,int)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
+ this, SIGNAL(itemsMoved(int,int,int)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(packageCreated(int,QmlPackage*)),
+ this, SLOT(_q_packageCreated(int,QmlPackage*)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(destroyingPackage(QmlPackage*)),
+ this, SLOT(_q_destroyingPackage(QmlPackage*)));
+ return;
+ }
+ if (!d->m_modelList)
+ d->m_modelList = new QmlListAccessor;
+ d->m_modelList->setList(model);
+ if (d->m_delegate && d->modelCount())
+ emit itemsInserted(0, d->modelCount());
+}
+
+QmlComponent *QFxVisualItemModel::delegate() const
+{
+ Q_D(const QFxVisualItemModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->delegate();
+ return d->m_delegate;
+}
+
+void QFxVisualItemModel::setDelegate(QmlComponent *delegate)
+{
+ Q_D(QFxVisualItemModel);
+ d->m_delegate = delegate;
+ if (d->modelCount())
+ emit itemsInserted(0, d->modelCount());
+}
+
+QString QFxVisualItemModel::part() const
+{
+ Q_D(const QFxVisualItemModel);
+ return d->m_part;
+}
+
+void QFxVisualItemModel::setPart(const QString &part)
+{
+ Q_D(QFxVisualItemModel);
+ d->m_part = part;
+}
+
+int QFxVisualItemModel::count() const
+{
+ Q_D(const QFxVisualItemModel);
+ return d->modelCount();
+}
+
+QFxItem *QFxVisualItemModel::item(int index, bool complete)
+{
+ Q_D(QFxVisualItemModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->item(index, d->m_part.toLatin1(), complete);
+ return item(index, QByteArray(), complete);
+}
+
+void QFxVisualItemModel::release(QFxItem *item)
+{
+ Q_D(QFxVisualItemModel);
+ if (d->m_visualItemModel) {
+ d->m_visualItemModel->release(item);
+ return;
+ }
+ item->setItemParent(0);
+ QObject *obj = item;
+
+ bool inPackage = false;
+ if (QmlPackage *package = d->m_packaged.value(item)) {
+ static_cast<QObject*>(item)->setParent(package);
+ d->m_packaged.remove(item);
+ //XXX Inefficient
+ for (QHash<QObject *, QmlPackage *>::Iterator iter = d->m_packaged.begin();
+ iter != d->m_packaged.end(); ++iter) {
+ if (*iter == package)
+ return;
+ }
+ inPackage = true;
+ obj = package; // fall through and delete
+ }
+
+ //XXX Inefficient
+ for (QHash<int, QObject *>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ++iter) {
+ if (*iter == obj) {
+ if (inPackage)
+ emit destroyingPackage(qobject_cast<QmlPackage*>(obj));
+ delete obj;
+ d->m_cache.erase(iter);
+ return;
+ }
+ }
+}
+
+QObject *QFxVisualItemModel::parts()
+{
+ Q_D(QFxVisualItemModel);
+ if (!d->m_parts)
+ d->m_parts = new QFxVisualItemModelParts(this);
+ return d->m_parts;
+}
+
+QFxItem *QFxVisualItemModel::item(int index, const QByteArray &viewId, bool complete)
+{
+ Q_D(QFxVisualItemModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->item(index, viewId, complete);
+
+ if (d->modelCount() <= 0 || !d->m_delegate)
+ return 0;
+
+ QObject *nobj = 0;
+ if (d->m_cache.contains(index)) {
+ nobj = d->m_cache[index];
+ } else {
+ QmlContext *ccontext = d->m_context;
+ if (!ccontext) ccontext = qmlContext(this);
+ QmlContext *ctxt = new QmlContext(ccontext);
+ QFxVisualItemModelData *data = new QFxVisualItemModelData(index, d);
+ ctxt->setContextProperty(QLatin1String("model"), data);
+ ctxt->addDefaultObject(data);
+ nobj = d->m_delegate->beginCreate(ctxt);
+ if (complete)
+ d->m_delegate->completeCreate();
+ if (nobj) {
+ ctxt->setParent(nobj);
+ data->setParent(nobj);
+
+ d->m_cache.insert(index, nobj);
+ } else {
+ delete data;
+ delete ctxt;
+ qWarning() << d->m_delegate->errors();
+ }
+ }
+ QFxItem *item = qobject_cast<QFxItem *>(nobj);
+ if (!item) {
+ QmlPackage *package = qobject_cast<QmlPackage *>(nobj);
+ if (package) {
+ QObject *o = package->part(QLatin1String(viewId));
+ item = qobject_cast<QFxItem *>(o);
+ d->m_packaged[o] = package;
+ emit packageCreated(index, package);
+ }
+ }
+
+ return item;
+}
+
+void QFxVisualItemModel::completeItem()
+{
+ Q_D(QFxVisualItemModel);
+ if (d->m_visualItemModel) {
+ d->m_visualItemModel->completeItem();
+ return;
+ }
+
+ d->m_delegate->completeCreate();
+}
+
+QVariant QFxVisualItemModel::evaluate(int index, const QString &expression, QObject *objectContext)
+{
+ Q_D(QFxVisualItemModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->evaluate(index, expression, objectContext);
+
+ if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
+ return QVariant();
+
+ QVariant value;
+ if (d->m_cache.contains(index)) {
+ QObject *nobj = d->m_cache[index];
+ QFxItem *item = qobject_cast<QFxItem *>(nobj);
+ if (item) {
+ QmlExpression e(qmlContext(item), expression, objectContext);
+ e.setTrackChange(false);
+ value = e.value();
+ }
+ } else {
+ QmlContext *ccontext = d->m_context;
+ if (!ccontext) ccontext = qmlContext(this);
+ QmlContext *ctxt = new QmlContext(ccontext);
+ QFxVisualItemModelData *data = new QFxVisualItemModelData(index, d);
+ ctxt->addDefaultObject(data);
+ QmlExpression e(ctxt, expression, objectContext);
+ e.setTrackChange(false);
+ value = e.value();
+ delete data;
+ delete ctxt;
+ }
+
+ return value;
+}
+
+void QFxVisualItemModel::_q_itemsChanged(int index, int count,
+ const QList<int> &roles)
+{
+ Q_D(QFxVisualItemModel);
+ // XXX - highly inefficient
+ for (int ii = index; ii < index + count; ++ii) {
+
+ if (d->m_cache.contains(ii)) {
+
+ QObject *item = d->m_cache[ii];
+ QFxVisualItemModelData *data = d->data(item);
+
+ for (int prop = 0; prop < data->count(); ++prop) {
+
+ int role = data->role(prop);
+ if (roles.contains(role)) {
+ if (d->m_listModelInterface) {
+ data->setValue(prop, *d->m_listModelInterface->data(ii, QList<int>() << role).begin());
+ } else if (d->m_abstractItemModel) {
+ QModelIndex index = d->m_abstractItemModel->index(ii, 0);
+ data->setValue(prop, d->m_abstractItemModel->data(index, role));
+ }
+ }
+ }
+ }
+
+ }
+}
+
+void QFxVisualItemModel::_q_itemsInserted(int index, int count)
+{
+ Q_D(QFxVisualItemModel);
+ // XXX - highly inefficient
+ QHash<int, QObject *> items;
+ for (QHash<int, QObject *>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ if (iter.key() >= index) {
+ QObject *item = *iter;
+ int index = iter.key() + count;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, item);
+
+ QFxVisualItemModelData *data = d->data(item);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+
+ emit itemsInserted(index, count);
+}
+
+void QFxVisualItemModel::_q_itemsRemoved(int index, int count)
+{
+ Q_D(QFxVisualItemModel);
+ // XXX - highly inefficient
+ QHash<int, QObject *> items;
+ for (QHash<int, QObject *>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+ if (iter.key() >= index && iter.key() < index + count) {
+ QObject *item = *iter;
+ iter = d->m_cache.erase(iter);
+ items.insertMulti(-1, item); //XXX perhaps better to maintain separately
+ QFxVisualItemModelData *data = d->data(item);
+ data->setIndex(-1);
+ } else if (iter.key() >= index + count) {
+ QObject *item = *iter;
+ int index = iter.key() - count;
+ iter = d->m_cache.erase(iter);
+ items.insert(index, item);
+ QFxVisualItemModelData *data = d->data(item);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+
+ d->m_cache.unite(items);
+ emit itemsRemoved(index, count);
+}
+
+void QFxVisualItemModel::_q_itemsMoved(int from, int to, int count)
+{
+ Q_D(QFxVisualItemModel);
+ // XXX - highly inefficient
+ QHash<int, QObject *> items;
+ for (QHash<int, QObject *>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ if (iter.key() >= from && iter.key() < from + count) {
+ QObject *item = *iter;
+ int index = iter.key() - from + to;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, item);
+
+ QFxVisualItemModelData *data = d->data(item);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+
+ emit itemsMoved(from, to, count);
+}
+
+void QFxVisualItemModel::_q_rowsInserted(const QModelIndex &, int begin, int end)
+{
+ _q_itemsInserted(begin, end - begin + 1);
+}
+
+void QFxVisualItemModel::_q_rowsRemoved(const QModelIndex &, int begin, int end)
+{
+ _q_itemsRemoved(begin, end - begin + 1);
+}
+
+void QFxVisualItemModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
+{
+ Q_D(QFxVisualItemModel);
+ _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
+}
+
+void QFxVisualItemModel::_q_packageCreated(int index, QmlPackage *package)
+{
+ Q_D(QFxVisualItemModel);
+ emit itemCreated(index, qobject_cast<QFxItem*>(package->part(d->m_part)));
+}
+
+void QFxVisualItemModel::_q_destroyingPackage(QmlPackage *package)
+{
+ Q_D(QFxVisualItemModel);
+ emit destroyingItem(qobject_cast<QFxItem*>(package->part(d->m_part)));
+}
+
+QML_DEFINE_TYPE(QFxVisualItemModel,VisualModel);
+
+QT_END_NAMESPACE
+#include "qfxvisualitemmodel.moc"
diff --git a/src/declarative/fx/qfxvisualitemmodel.h b/src/declarative/fx/qfxvisualitemmodel.h
new file mode 100644
index 0000000..33017e2
--- /dev/null
+++ b/src/declarative/fx/qfxvisualitemmodel.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXVISUALITEMMODEL_H
+#define QFXVISUALITEMMODEL_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qabstractitemmodel.h>
+#include <qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+/*****************************************************************************
+ *****************************************************************************
+ XXX Experimental
+ *****************************************************************************
+*****************************************************************************/
+
+class QFxItem;
+class QmlComponent;
+class QmlPackage;
+class QFxVisualItemModelPrivate;
+class QFxVisualItemModel : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFxVisualItemModel)
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(QString part READ part WRITE setPart)
+ Q_PROPERTY(QObject *parts READ parts)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+public:
+ QFxVisualItemModel();
+ QFxVisualItemModel(QmlContext *);
+ virtual ~QFxVisualItemModel();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QmlComponent *delegate() const;
+ void setDelegate(QmlComponent *);
+
+ QString part() const;
+ void setPart(const QString &);
+
+ int count() const;
+ QFxItem *item(int index, bool complete=true);
+ QFxItem *item(int index, const QByteArray &, bool complete=true);
+ void release(QFxItem *item);
+ void completeItem();
+ QVariant evaluate(int index, const QString &expression, QObject *objectContext);
+
+ QObject *parts();
+
+Q_SIGNALS:
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void itemCreated(int index, QFxItem *item);
+ void packageCreated(int index, QmlPackage *package);
+ void destroyingItem(QFxItem *item);
+ void destroyingPackage(QmlPackage *package);
+
+private Q_SLOTS:
+ void _q_itemsChanged(int, int, const QList<int> &);
+ void _q_itemsInserted(int index, int count);
+ void _q_itemsRemoved(int index, int count);
+ void _q_itemsMoved(int from, int to, int count);
+ void _q_rowsInserted(const QModelIndex &,int,int);
+ void _q_rowsRemoved(const QModelIndex &,int,int);
+ void _q_dataChanged(const QModelIndex&,const QModelIndex&);
+ void _q_packageCreated(int index, QmlPackage *package);
+ void _q_destroyingPackage(QmlPackage *package);
+
+private:
+ Q_DISABLE_COPY(QFxVisualItemModel)
+};
+QML_DECLARE_TYPE(QFxVisualItemModel);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXVISUALITEMMODEL_H
diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp
new file mode 100644
index 0000000..7998711
--- /dev/null
+++ b/src/declarative/fx/qfxwebview.cpp
@@ -0,0 +1,1076 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include <QPen>
+#include <QFile>
+#include <QEvent>
+#include <QBasicTimer>
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+#include <QtWebKit/QWebPage>
+#include <QtWebKit/QWebFrame>
+
+#include "qml.h"
+#include "qmlbindablevalue.h"
+#include "qmlengine.h"
+#include "qmlstate.h"
+#include "qfxtransform.h"
+#include "qfxscalegrid.h"
+#include "qsimplecanvas.h"
+#include "qlistmodelinterface.h"
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <QtOpenGL/qglframebufferobject.h>
+#include <glsave.h>
+#endif
+#if defined(QFX_RENDER_OPENGL)
+#include <gltexture.h>
+#endif
+
+#include "qfxwebview.h"
+#include <qsimplecanvasfilter.h>
+#include <private/qfxpainteditem_p.h>
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QFxWebView,WebView);
+
+static const int MAX_DOUBLECLICK_TIME=500; // XXX need better gesture system
+
+class QFxWebSettings : public QObject {
+ Q_OBJECT
+ /*
+ StandardFont,
+ FixedFont,
+ SerifFont,
+ SansSerifFont,
+ CursiveFont,
+ FantasyFont
+
+ MinimumFontSize,
+ MinimumLogicalFontSize,
+ DefaultFontSize,
+ DefaultFixedFontSize
+ */
+
+ Q_PROPERTY(bool autoLoadImages READ autoLoadImages WRITE setAutoLoadImages)
+ Q_PROPERTY(bool javascriptEnabled READ javascriptEnabled WRITE setJavascriptEnabled)
+ Q_PROPERTY(bool javaEnabled READ javaEnabled WRITE setJavaEnabled)
+ Q_PROPERTY(bool pluginsEnabled READ pluginsEnabled WRITE setPluginsEnabled)
+ Q_PROPERTY(bool privateBrowsingEnabled READ privateBrowsingEnabled WRITE setPrivateBrowsingEnabled)
+ Q_PROPERTY(bool javascriptCanOpenWindows READ javascriptCanOpenWindows WRITE setJavascriptCanOpenWindows)
+ Q_PROPERTY(bool javascriptCanAccessClipboard READ javascriptCanAccessClipboard WRITE setJavascriptCanAccessClipboard)
+ Q_PROPERTY(bool developerExtrasEnabled READ developerExtrasEnabled WRITE setDeveloperExtrasEnabled)
+ Q_PROPERTY(bool linksIncludedInFocusChain READ linksIncludedInFocusChain WRITE setLinksIncludedInFocusChain)
+ Q_PROPERTY(bool zoomTextOnly READ zoomTextOnly WRITE setZoomTextOnly)
+ Q_PROPERTY(bool printElementBackgrounds READ printElementBackgrounds WRITE setPrintElementBackgrounds)
+ Q_PROPERTY(bool offlineStorageDatabaseEnabled READ offlineStorageDatabaseEnabled WRITE setOfflineStorageDatabaseEnabled)
+ Q_PROPERTY(bool offlineWebApplicationCacheEnabled READ offlineWebApplicationCacheEnabled WRITE setOfflineWebApplicationCacheEnabled)
+ Q_PROPERTY(bool localStorageDatabaseEnabled READ localStorageDatabaseEnabled WRITE setLocalStorageDatabaseEnabled)
+
+public:
+ QFxWebSettings() {}
+
+ bool autoLoadImages() const { return s->testAttribute(QWebSettings::AutoLoadImages); }
+ void setAutoLoadImages(bool on) { s->setAttribute(QWebSettings::AutoLoadImages, on); }
+ bool javascriptEnabled() const { return s->testAttribute(QWebSettings::JavascriptEnabled); }
+ void setJavascriptEnabled(bool on) { s->setAttribute(QWebSettings::JavascriptEnabled, on); }
+ bool javaEnabled() const { return s->testAttribute(QWebSettings::JavaEnabled); }
+ void setJavaEnabled(bool on) { s->setAttribute(QWebSettings::JavaEnabled, on); }
+ bool pluginsEnabled() const { return s->testAttribute(QWebSettings::PluginsEnabled); }
+ void setPluginsEnabled(bool on) { s->setAttribute(QWebSettings::PluginsEnabled, on); }
+ bool privateBrowsingEnabled() const { return s->testAttribute(QWebSettings::PrivateBrowsingEnabled); }
+ void setPrivateBrowsingEnabled(bool on) { s->setAttribute(QWebSettings::PrivateBrowsingEnabled, on); }
+ bool javascriptCanOpenWindows() const { return s->testAttribute(QWebSettings::JavascriptCanOpenWindows); }
+ void setJavascriptCanOpenWindows(bool on) { s->setAttribute(QWebSettings::JavascriptCanOpenWindows, on); }
+ bool javascriptCanAccessClipboard() const { return s->testAttribute(QWebSettings::JavascriptCanAccessClipboard); }
+ void setJavascriptCanAccessClipboard(bool on) { s->setAttribute(QWebSettings::JavascriptCanAccessClipboard, on); }
+ bool developerExtrasEnabled() const { return s->testAttribute(QWebSettings::DeveloperExtrasEnabled); }
+ void setDeveloperExtrasEnabled(bool on) { s->setAttribute(QWebSettings::DeveloperExtrasEnabled, on); }
+ bool linksIncludedInFocusChain() const { return s->testAttribute(QWebSettings::LinksIncludedInFocusChain); }
+ void setLinksIncludedInFocusChain(bool on) { s->setAttribute(QWebSettings::LinksIncludedInFocusChain, on); }
+ bool zoomTextOnly() const { return s->testAttribute(QWebSettings::ZoomTextOnly); }
+ void setZoomTextOnly(bool on) { s->setAttribute(QWebSettings::ZoomTextOnly, on); }
+ bool printElementBackgrounds() const { return s->testAttribute(QWebSettings::PrintElementBackgrounds); }
+ void setPrintElementBackgrounds(bool on) { s->setAttribute(QWebSettings::PrintElementBackgrounds, on); }
+ bool offlineStorageDatabaseEnabled() const { return s->testAttribute(QWebSettings::OfflineStorageDatabaseEnabled); }
+ void setOfflineStorageDatabaseEnabled(bool on) { s->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, on); }
+ bool offlineWebApplicationCacheEnabled() const { return s->testAttribute(QWebSettings::OfflineWebApplicationCacheEnabled); }
+ void setOfflineWebApplicationCacheEnabled(bool on) { s->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, on); }
+ bool localStorageDatabaseEnabled() const { return s->testAttribute(QWebSettings::LocalStorageDatabaseEnabled); }
+ void setLocalStorageDatabaseEnabled(bool on) { s->setAttribute(QWebSettings::LocalStorageDatabaseEnabled, on); }
+
+ QWebSettings *s;
+};
+
+
+class QFxWebViewPrivate : public QFxPaintedItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxWebView)
+
+public:
+ QFxWebViewPrivate()
+ : QFxPaintedItemPrivate(), page(0), idealwidth(0), idealheight(0), interactive(true), lastPress(0), lastRelease(0), mouseX(0), mouseY(0),
+ max_imagecache_size(100000), progress(1.0), pending(PendingNone)
+ {
+ }
+
+ QWebPage *page;
+
+ struct ImageCacheItem {
+ ImageCacheItem() : age(0) {}
+ ~ImageCacheItem() { }
+ int age;
+ QRect area;
+#if defined(QFX_RENDER_QPAINTER)
+ QSimpleCanvasConfig::Image image;
+#else
+ GLTexture image;
+#endif
+ };
+ QList<ImageCacheItem*> imagecache;
+ void dirtyCache(const QRect& dirt)
+ {
+ for (int i=0; i<imagecache.count(); ) {
+ if (imagecache[i]->area.intersects(dirt)) {
+ imagecache.removeAt(i);
+ } else {
+ ++i;
+ }
+ }
+ }
+ void clearCache()
+ {
+ foreach (ImageCacheItem* i, imagecache)
+ delete i;
+ imagecache.clear();
+ }
+
+ int idealwidth;
+ int idealheight;
+ bool interactive;
+ QMouseEvent *lastPress, *lastRelease;
+ int mouseX, mouseY;
+ int max_imagecache_size;
+ qreal progress;
+ QBasicTimer dcTimer;
+ QString statusBarMessage;
+ enum { PendingNone, PendingUrl, PendingHtml, PendingContent } pending;
+ QUrl pending_url;
+ QString pending_string;
+ QByteArray pending_data;
+ mutable QFxWebSettings settings;
+};
+
+
+/*!
+ \qmlclass WebView
+ \brief The WebView item allows you to add web content to a canvas.
+ \inherits Item
+
+ A WebView renders web content based on a URL.
+
+ If the width and height of the item is not set, they will
+ dynamically adjust to a size appropriate for the content.
+ This width may be large (eg. 980) for typical online web pages.
+
+ If the idealWidth is set, the width will be this amount or larger,
+ usually laying out the web content to fit the idealWidth.
+
+ If the idealHeight is set, the height will be this amount or larger.
+ Due to WebKit limitations, the height may be more than necessary
+ if the idealHeight is changed after the content is loaded.
+
+ \qml
+ WebView {
+ url: "http://www.nokia.com"
+ width: 490
+ height: 400
+ scale: 0.5
+ smooth: true
+ }
+ \endqml
+
+ \image webview.png
+
+ The item includes no scrolling, scaling,
+ toolbars, etc., those must be implemented around WebView. See the WebBrowser example
+ for a demonstration of this.
+*/
+
+/*!
+ \internal
+ \class QFxWebView
+ \brief The QFxWebView class allows you to add web content to a QFxView.
+
+ A WebView renders web content base on a URL.
+
+ \image webview.png
+
+ The item includes no scrolling, scaling,
+ toolbars, etc., those must be implemented around WebView. See the WebBrowser example
+ for a demonstration of this.
+
+ A QFxWebView object can be instantiated in Qml using the tag \l WebView.
+*/
+
+QFxWebView::QFxWebView(QFxItem *parent)
+ : QFxPaintedItem(*(new QFxWebViewPrivate), parent)
+{
+ init();
+}
+
+QFxWebView::QFxWebView(QFxWebViewPrivate &dd, QFxItem *parent)
+ : QFxPaintedItem(dd, parent)
+{
+ init();
+}
+
+QFxWebView::~QFxWebView()
+{
+ Q_D(QFxWebView);
+ delete d->page;
+}
+
+void QFxWebView::init()
+{
+ Q_D(QFxWebView);
+
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setOptions(HasContents | MouseEvents);
+ setFocusable(true);
+
+ d->page = 0;
+}
+
+void QFxWebView::componentComplete()
+{
+ QFxPaintedItem::componentComplete();
+ Q_D(QFxWebView);
+ switch (d->pending) {
+ case QFxWebViewPrivate::PendingUrl:
+ setUrl(d->pending_url.toString());
+ break;
+ case QFxWebViewPrivate::PendingHtml:
+ setHtml(d->pending_string, d->pending_url);
+ break;
+ case QFxWebViewPrivate::PendingContent:
+ setContent(d->pending_data, d->pending_string, d->pending_url);
+ break;
+ default:
+ break;
+ }
+ d->pending = QFxWebViewPrivate::PendingNone;
+}
+
+/*!
+ \qmlproperty real WebView::progress
+ This property holds the progress of loading the current URL, from 0 to 1.
+*/
+/*!
+ \property QFxWebView::progress
+ \brief the progress of loading the current URL, from 0 to 1.
+*/
+qreal QFxWebView::progress() const
+{
+ Q_D(const QFxWebView);
+ return d->progress;
+}
+
+void QFxWebView::doLoadProgress(int p)
+{
+ Q_D(QFxWebView);
+ if (d->progress == p/100.0)
+ return;
+ d->progress = p/100.0;
+ expandToWebPage();
+ emit progressChanged();
+}
+
+void QFxWebView::doLoadFinished(bool ok)
+{
+ // XXX bug 232556 - pages with no title never get this signal
+ if (title().isEmpty())
+ emit urlChanged();
+
+ if (ok) {
+ emit loadFinished();
+ } else {
+ emit loadFailed();
+ }
+}
+
+/*!
+ \qmlproperty string WebView::url
+ This property holds the URL to the page displayed in this item.
+
+ Note that after this property is set, it may take some time
+ before the change is notified, as this only happens when
+ loading of the URL successfully starts.
+*/
+/*!
+ \property QFxWebView::url
+ \brief the URL to the page displayed in this item.
+
+ \sa urlChanged()
+*/
+/*!
+ \fn void QFxWebView::urlChanged()
+
+ Emitted when loading of the URL successfully starts after
+ setUrl() is called.
+*/
+QString QFxWebView::url() const
+{
+ return page()->mainFrame()->url().toString();
+}
+
+void QFxWebView::setUrl(const QString &n)
+{
+ Q_D(QFxWebView);
+ if (n == page()->mainFrame()->url().toString())
+ return;
+
+ page()->setViewportSize(QSize(
+ d->idealwidth>0 ? d->idealwidth : width(),
+ d->idealheight>0 ? d->idealheight : height()));
+
+ QUrl url(n);
+ if (url.isRelative())
+ url = qmlContext(this)->resolvedUrl(n);
+
+ if (isComponentComplete())
+ page()->mainFrame()->load(url);
+ else {
+ d->pending = d->PendingUrl;
+ d->pending_url = url;
+ }
+
+ // emit urlChanged() - not until actually loaded
+}
+
+/*!
+ \qmlproperty int WebView::idealWidth
+ This property holds the ideal width for displaying the current URL.
+*/
+/*!
+ \property QFxWebView::idealWidth
+ \brief the ideal width for displaying the current URL.
+*/
+int QFxWebView::idealWidth() const
+{
+ Q_D(const QFxWebView);
+ return d->idealwidth;
+}
+
+void QFxWebView::setIdealWidth(int iw)
+{
+ Q_D(QFxWebView);
+ if (d->idealwidth == iw) return;
+ d->idealwidth = iw;
+ expandToWebPage();
+ emit idealWidthChanged();
+}
+
+/*!
+ \qmlproperty int WebView::idealHeight
+ This property holds the ideal height for displaying the current URL.
+*/
+/*!
+ \property QFxWebView::idealHeight
+ \brief the ideal height for displaying the current URL.
+*/
+int QFxWebView::idealHeight() const
+{
+ Q_D(const QFxWebView);
+ return d->idealheight;
+}
+
+void QFxWebView::setIdealHeight(int ih)
+{
+ Q_D(QFxWebView);
+ if (d->idealheight == ih) return;
+ d->idealheight = ih;
+ expandToWebPage();
+ emit idealHeightChanged();
+}
+
+/*!
+ \qmlproperty bool WebView::interactive
+
+ This property holds controls whether the item responds to mouse and
+ key events.
+*/
+
+/*!
+ \property QFxWebView::interactive
+
+ \brief controls whether the item responds to mouse and key events.
+*/
+bool QFxWebView::interactive() const
+{
+ Q_D(const QFxWebView);
+ return d->interactive;
+}
+
+void QFxWebView::setInteractive(bool i)
+{
+ Q_D(QFxWebView);
+ if (d->interactive == i) return;
+ d->interactive = i;
+ emit interactiveChanged();
+}
+
+void QFxWebView::updateCacheForVisibility()
+{
+ Q_D(QFxWebView);
+ if (!isVisible())
+ d->clearCache();
+}
+
+void QFxWebView::expandToWebPage()
+{
+ Q_D(QFxWebView);
+ QSize cs = page()->mainFrame()->contentsSize();
+ if (cs.width() < d->idealwidth)
+ cs.setWidth(d->idealwidth);
+ if (cs.height() < d->idealheight)
+ cs.setHeight(d->idealheight);
+ if (widthValid() && cs.width() < width())
+ cs.setWidth(width());
+ if (heightValid() && cs.height() < height())
+ cs.setHeight(height());
+ if (cs != page()->viewportSize()) {
+ page()->setViewportSize(cs);
+ d->clearCache();
+ setImplicitWidth(cs.width());
+ setImplicitHeight(cs.height());
+ }
+}
+
+void QFxWebView::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ if (newGeometry.size() != oldGeometry.size())
+ expandToWebPage();
+ QFxPaintedItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+void QFxWebView::paintPage(const QRect& r)
+{
+ Q_D(QFxWebView);
+ if (d->page->mainFrame()->contentsSize() != contentsSize())
+ setContentsSize(d->page->mainFrame()->contentsSize());
+ dirtyCache(r);
+ update();
+}
+
+/*!
+ \qmlproperty int WebView::cacheSize
+
+ This property holds the maximum number of pixels of image cache to
+ allow. The default is 0.1 megapixels. The cache will not be larger
+ than the (unscaled) size of the WebView.
+*/
+
+/*!
+ \property QFxWebView::cacheSize
+
+ The maximum number of pixels of image cache to allow. The default
+ is 0.1 megapixels. The cache will not be larger than the (unscaled)
+ size of the QFxWebView.
+*/
+int QFxWebView::cacheSize() const
+{
+ Q_D(const QFxWebView);
+ return d->max_imagecache_size;
+}
+
+void QFxWebView::setCacheSize(int pixels)
+{
+ Q_D(QFxWebView);
+ if (pixels < d->max_imagecache_size) {
+ int cachesize=0;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ QRect area = d->imagecache[i]->area;
+ cachesize += area.width()*area.height();
+ }
+ while (d->imagecache.count() && cachesize > pixels) {
+ int oldest=-1;
+ int age=-1;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ int a = d->imagecache[i]->age;
+ if (a > age) {
+ oldest = i;
+ age = a;
+ }
+ }
+ cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
+ d->imagecache.removeAt(oldest);
+ }
+ }
+ d->max_imagecache_size = pixels;
+}
+
+void QFxWebView::dump(int depth)
+{
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba.constData() << "url:" << url();
+ QFxPaintedItem::dump(depth);
+}
+
+void QFxWebView::drawContents(QPainter *p, const QRect &r)
+{
+ page()->mainFrame()->render(p,r);
+}
+
+QString QFxWebView::propertyInfo() const
+{
+ return page()->mainFrame()->url().toString();
+}
+
+static QMouseEvent *sceneMouseEventToMouseEvent(QGraphicsSceneMouseEvent *e)
+{
+ QEvent::Type t;
+ switch(e->type()) {
+ default:
+ case QEvent::GraphicsSceneMousePress:
+ t = QEvent::MouseButtonPress;
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ t = QEvent::MouseButtonRelease;
+ break;
+ case QEvent::GraphicsSceneMouseMove:
+ t = QEvent::MouseMove;
+ break;
+ case QGraphicsSceneEvent::GraphicsSceneMouseDoubleClick:
+ t = QEvent::MouseButtonDblClick;
+ break;
+ }
+
+ QMouseEvent *me = new QMouseEvent(t, e->pos().toPoint(), e->button(), e->buttons(), 0);
+ return me;
+}
+
+
+void QFxWebView::timerEvent(QTimerEvent *event)
+{
+ Q_D(QFxWebView);
+ if (event->timerId() ==d->dcTimer.timerId()) {
+ d->dcTimer.stop();
+ if (d->lastPress) {
+ page()->event(d->lastPress);
+ delete d->lastPress;
+ d->lastPress = 0;
+ }
+ if (d->lastRelease) {
+ page()->event(d->lastRelease);
+ delete d->lastRelease;
+ d->lastRelease = 0;
+ }
+ }
+}
+
+int QFxWebView::mouseX() const
+{
+ Q_D(const QFxWebView);
+ if (d->lastPress)
+ return d->lastPress->x();
+ if (d->lastRelease)
+ return d->lastRelease->x();
+ return d->mouseX;
+}
+
+int QFxWebView::mouseY() const
+{
+ Q_D(const QFxWebView);
+ if (d->lastPress)
+ return d->lastPress->y();
+ if (d->lastRelease)
+ return d->lastRelease->y();
+ return d->mouseY;
+}
+
+void QFxWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ QMouseEvent *me = sceneMouseEventToMouseEvent(event);
+ Q_D(QFxWebView);
+ d->dcTimer.stop();
+ delete d->lastPress;
+ delete d->lastRelease;
+ d->lastPress = 0;
+ d->lastRelease = 0;
+ d->mouseX = me->x();
+ d->mouseY = me->y();
+ emit doubleClick();
+ d->mouseX = 0;
+ d->mouseY = 0;
+ delete me;
+}
+
+void QFxWebView::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxWebView);
+ if (d->interactive) {
+ d->lastPress = sceneMouseEventToMouseEvent(event);
+ event->setAccepted(true);
+ } else {
+ event->setAccepted(false);
+ }
+ if (!event->isAccepted())
+ QFxPaintedItem::mousePressEvent(event);
+}
+
+void QFxWebView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxWebView);
+ if (d->interactive) {
+ d->lastRelease = sceneMouseEventToMouseEvent(event);
+ d->dcTimer.start(MAX_DOUBLECLICK_TIME,this);
+ event->setAccepted(true);
+ } else {
+ event->setAccepted(false);
+ }
+ if (!event->isAccepted())
+ QFxPaintedItem::mouseReleaseEvent(event);
+}
+
+void QFxWebView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(const QFxWebView);
+ if (d->interactive && !d->dcTimer.isActive()) {
+ QMouseEvent *me = sceneMouseEventToMouseEvent(event);
+ page()->event(me);
+ event->setAccepted(
+#if QT_VERSION <= 0x040500 // XXX see bug 230835
+ true
+#else
+ me->isAccepted()
+#endif
+ );
+ delete me;
+ } else {
+ event->setAccepted(false);
+ }
+ if (!event->isAccepted())
+ QFxPaintedItem::mouseMoveEvent(event);
+}
+
+void QFxWebView::keyPressEvent(QKeyEvent* event)
+{
+ Q_D(const QFxWebView);
+ if (d->interactive)
+ page()->event(event);
+ if (!event->isAccepted())
+ QFxPaintedItem::keyPressEvent(event);
+}
+
+void QFxWebView::keyReleaseEvent(QKeyEvent* event)
+{
+ Q_D(const QFxWebView);
+ if (d->interactive)
+ page()->event(event);
+ if (!event->isAccepted())
+ QFxPaintedItem::keyReleaseEvent(event);
+}
+
+/*!
+ \qmlproperty action WebView::back
+ This property holds the action for causing the previous URL in the history to be displayed.
+*/
+QAction *QFxWebView::backAction() const
+{
+ return page()->action(QWebPage::Back);
+}
+
+/*!
+ \qmlproperty action WebView::forward
+ This property holds the action for causing the next URL in the history to be displayed.
+*/
+QAction *QFxWebView::forwardAction() const
+{
+ return page()->action(QWebPage::Forward);
+}
+
+/*!
+ \qmlproperty action WebView::reload
+ This property holds the action for reloading with the current URL
+*/
+QAction *QFxWebView::reloadAction() const
+{
+ return page()->action(QWebPage::Reload);
+}
+
+/*!
+ \qmlproperty action WebView::stop
+ This property holds the action for stopping loading with the current URL
+*/
+QAction *QFxWebView::stopAction() const
+{
+ return page()->action(QWebPage::Stop);
+}
+
+/*!
+ \qmlproperty real WebView::title
+ This property holds the title of the web page currently viewed
+
+ By default, this property contains an empty string.
+*/
+/*!
+ \property QFxWebView::title
+ This property holds the title of the web page currently viewed
+
+ By default, this property contains an empty string.
+
+ \sa titleChanged()
+*/
+QString QFxWebView::title() const
+{
+ return page()->mainFrame()->title();
+}
+
+
+
+/*!
+ \qmlproperty pixmap WebView::icon
+ This property holds the icon associated with the web page currently viewed
+*/
+/*!
+ \property QFxWebView::icon
+ \brief the icon associated with the web page currently viewed
+
+ By default, this property contains a null icon.
+
+ \sa iconChanged(), QWebSettings::iconForUrl()
+*/
+QPixmap QFxWebView::icon() const
+{
+ return page()->mainFrame()->icon().pixmap(QSize(256,256));
+}
+
+
+/*!
+ \qmlproperty real WebView::textSizeMultiplier
+ This property holds multiplier used to scale the text in a Web page
+*/
+/*!
+ Sets the value of the multiplier used to scale the text in a Web page to
+ the \a factor specified.
+*/
+void QFxWebView::setTextSizeMultiplier(qreal factor)
+{
+ page()->mainFrame()->setTextSizeMultiplier(factor);
+}
+
+/*!
+ Returns the value of the multiplier used to scale the text in a Web page.
+*/
+qreal QFxWebView::textSizeMultiplier() const
+{
+ return page()->mainFrame()->textSizeMultiplier();
+}
+
+void QFxWebView::setStatusBarMessage(const QString& s)
+{
+ Q_D(QFxWebView);
+ d->statusBarMessage = s;
+ emit statusChanged();
+}
+
+QString QFxWebView::status() const
+{
+ Q_D(const QFxWebView);
+ return d->statusBarMessage;
+}
+
+QWebPage *QFxWebView::page() const
+{
+ Q_D(const QFxWebView);
+
+ if (!d->page) {
+ QFxWebView *self = const_cast<QFxWebView*>(this);
+ QWebPage *wp = new QFxWebPage(self);
+
+ // QML items don't default to having a background,
+ // even though most we pages will set one anyway.
+ QPalette pal = QApplication::palette();
+ pal.setBrush(QPalette::Base, QColor::fromRgbF(0, 0, 0, 0));
+ wp->setPalette(pal);
+
+ wp->setNetworkAccessManager(qmlEngine(this)->networkAccessManager());
+
+ self->setPage(wp);
+
+ return wp;
+ }
+
+ return d->page;
+}
+
+
+// The QObject interface to settings().
+/*!
+ \qmlproperty bool WebView::settings.autoLoadImages
+ \qmlproperty bool WebView::settings.javascriptEnabled
+ \qmlproperty bool WebView::settings.javaEnabled
+ \qmlproperty bool WebView::settings.pluginsEnabled
+ \qmlproperty bool WebView::settings.privateBrowsingEnabled
+ \qmlproperty bool WebView::settings.javascriptCanOpenWindows
+ \qmlproperty bool WebView::settings.javascriptCanAccessClipboard
+ \qmlproperty bool WebView::settings.developerExtrasEnabled
+ \qmlproperty bool WebView::settings.linksIncludedInFocusChain
+ \qmlproperty bool WebView::settings.zoomTextOnly
+ \qmlproperty bool WebView::settings.printElementBackgrounds
+ \qmlproperty bool WebView::settings.offlineStorageDatabaseEnabled
+ \qmlproperty bool WebView::settings.offlineWebApplicationCacheEnabled
+ \qmlproperty bool WebView::settings.localStorageDatabaseEnabled
+
+ These properties give access to the settings controlling the web view.
+
+ See QWebSettings for the list of sub-properties.
+
+ \qml
+ WebView {
+ settings.pluginsEnabled: true
+ ...
+ }
+ \endqml
+*/
+QObject *QFxWebView::settingsObject() const
+{
+ Q_D(const QFxWebView);
+ d->settings.s = page()->settings();
+ return &d->settings;
+}
+
+void QFxWebView::setPage(QWebPage *page)
+{
+ Q_D(QFxWebView);
+ if (d->page == page)
+ return;
+ if (d->page) {
+ if (d->page->parent() == this) {
+ delete d->page;
+ } else {
+ d->page->disconnect(this);
+ }
+ }
+ d->page = page;
+ d->page->setViewportSize(QSize(
+ d->idealwidth>0 ? d->idealwidth : -1,
+ d->idealheight>0 ? d->idealheight : -1));
+ d->page->mainFrame()->setScrollBarPolicy(Qt::Horizontal,Qt::ScrollBarAlwaysOff);
+ d->page->mainFrame()->setScrollBarPolicy(Qt::Vertical,Qt::ScrollBarAlwaysOff);
+ connect(this,SIGNAL(visibleChanged()),this,SLOT(updateCacheForVisibility()));
+ connect(d->page,SIGNAL(repaintRequested(QRect)),this,SLOT(paintPage(QRect)));
+ connect(d->page->mainFrame(),SIGNAL(urlChanged(QUrl)),this,SIGNAL(urlChanged()));
+ connect(d->page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString)));
+ connect(d->page->mainFrame(), SIGNAL(iconChanged()), this, SIGNAL(iconChanged()));
+
+ connect(d->page,SIGNAL(loadStarted()),this,SIGNAL(loadStarted()));
+ connect(d->page,SIGNAL(loadProgress(int)),this,SLOT(doLoadProgress(int)));
+ connect(d->page,SIGNAL(loadFinished(bool)),this,SLOT(doLoadFinished(bool)));
+ connect(d->page,SIGNAL(statusBarMessage(QString)),this,SLOT(setStatusBarMessage(QString)));
+}
+
+void QFxWebView::load(const QNetworkRequest &request,
+ QNetworkAccessManager::Operation operation,
+ const QByteArray &body)
+{
+ page()->mainFrame()->load(request, operation, body);
+}
+
+QString QFxWebView::html() const
+{
+ return page()->mainFrame()->toHtml();
+}
+
+/*!
+ \qmlproperty string WebView::html
+ This property holds HTML text set directly
+
+ The html property can be set as a string.
+
+ \qml
+ WebView {
+ html: "<p>This is <b>HTML</b>."
+ }
+ \endqml
+*/
+void QFxWebView::setHtml(const QString &html, const QUrl &baseUrl)
+{
+ Q_D(QFxWebView);
+ page()->setViewportSize(QSize(
+ d->idealwidth>0 ? d->idealwidth : width(),
+ d->idealheight>0 ? d->idealheight : height()));
+ if (isComponentComplete())
+ page()->mainFrame()->setHtml(html, qmlContext(this)->resolvedUrl(baseUrl));
+ else {
+ d->pending = d->PendingHtml;
+ d->pending_url = baseUrl;
+ d->pending_string = html;
+ }
+}
+
+void QFxWebView::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
+{
+ Q_D(QFxWebView);
+ page()->setViewportSize(QSize(
+ d->idealwidth>0 ? d->idealwidth : width(),
+ d->idealheight>0 ? d->idealheight : height()));
+
+ if (isComponentComplete())
+ page()->mainFrame()->setContent(data,mimeType,qmlContext(this)->resolvedUrl(baseUrl));
+ else {
+ d->pending = d->PendingContent;
+ d->pending_url = baseUrl;
+ d->pending_string = mimeType;
+ d->pending_data = data;
+ }
+}
+
+QWebHistory *QFxWebView::history() const
+{
+ return page()->history();
+}
+
+QWebSettings *QFxWebView::settings() const
+{
+ return page()->settings();
+}
+
+/*!
+ \internal
+ \class QFxWebPage
+ \brief The QFxWebPage class is a QWebPage that can create QML plugins.
+
+ \sa QFxWebView
+*/
+QFxWebPage::QFxWebPage(QFxWebView *parent) :
+ QWebPage(parent)
+{
+}
+
+QFxWebPage::~QFxWebPage()
+{
+}
+
+/*
+ Qt WebKit does not understand non-QWidget plugins, so dummy widgets
+ are created, parented to a single dummy tool window.
+
+ The requirements for QML object plugins are input to the Qt WebKit
+ non-QWidget plugin support, which will obsolete this kludge.
+*/
+class QWidget_Dummy_Plugin : public QWidget
+{
+ Q_OBJECT
+public:
+ static QWidget *dummy_shared_parent()
+ {
+ static QWidget *dsp = 0;
+ if (!dsp) {
+ dsp = new QWidget(0,Qt::Tool);
+ dsp->setGeometry(-10000,-10000,0,0);
+ dsp->show();
+ }
+ return dsp;
+ }
+ QWidget_Dummy_Plugin(const QUrl& url, QFxWebView *view, const QStringList &paramNames, const QStringList &paramValues) :
+ QWidget(dummy_shared_parent()),
+ propertyNames(paramNames),
+ propertyValues(paramValues),
+ webview(view)
+ {
+ QmlEngine *engine = qmlEngine(webview);
+ component = new QmlComponent(engine, url, this);
+ item = 0;
+ if (component->isReady())
+ qmlLoaded();
+ else
+ connect(component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(qmlLoaded()));
+ }
+
+public Q_SLOTS:
+ void qmlLoaded()
+ {
+ item = qobject_cast<QFxItem*>(component->create(qmlContext(webview)));
+ item->setParent(webview);
+ for (int i=0; i<propertyNames.count(); ++i) {
+ if (propertyNames[i] != QLatin1String("type") && propertyNames[i] != QLatin1String("data")) {
+ item->setProperty(propertyNames[i].toLatin1(),propertyValues[i]);
+ }
+ }
+ resizeEvent(0);
+ delete component;
+ component = 0;
+ }
+ void resizeEvent(QResizeEvent*)
+ {
+ if (item) {
+ item->setX(x());
+ item->setY(y());
+ item->setWidth(width());
+ item->setHeight(height());
+ }
+ }
+
+private:
+ QmlComponent *component;
+ QFxItem *item;
+ QStringList propertyNames, propertyValues;
+ QFxWebView *webview;
+};
+
+QFxWebView *QFxWebPage::view()
+{
+ return static_cast<QFxWebView*>(parent());
+}
+
+QObject *QFxWebPage::createPlugin(const QString &, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
+{
+ QUrl comp = qmlContext(view())->resolvedUri(url.toString());
+ return new QWidget_Dummy_Plugin(comp,view(),paramNames,paramValues);
+}
+
+#include "qfxwebview.moc"
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxwebview.h b/src/declarative/fx/qfxwebview.h
new file mode 100644
index 0000000..afd5b0f
--- /dev/null
+++ b/src/declarative/fx/qfxwebview.h
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXWEBVIEW_H
+#define QFXWEBVIEW_H
+
+#include <QAction>
+#include <QUrl>
+#include <qfxglobal.h>
+#include <qfxpainteditem.h>
+#include <QtNetwork/qnetworkaccessmanager.h>
+#include <QWebPage>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QWebHistory;
+class QWebSettings;
+class QFxWebViewPrivate;
+class QNetworkRequest;
+class QFxWebView;
+
+class Q_DECLARATIVE_EXPORT QFxWebPage : public QWebPage
+{
+ Q_OBJECT
+public:
+ explicit QFxWebPage(QFxWebView *parent);
+ ~QFxWebPage();
+protected:
+ QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues);
+private:
+ QFxWebView *view();
+};
+
+
+class Q_DECLARATIVE_EXPORT QFxWebView : public QFxPaintedItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString title READ title NOTIFY titleChanged)
+ Q_PROPERTY(QPixmap icon READ icon NOTIFY iconChanged)
+ Q_PROPERTY(qreal textSizeMultiplier READ textSizeMultiplier WRITE setTextSizeMultiplier DESIGNABLE false)
+ Q_PROPERTY(QString status READ status NOTIFY statusChanged)
+
+ Q_PROPERTY(int mouseX READ mouseX)
+ Q_PROPERTY(int mouseY READ mouseY)
+
+ Q_PROPERTY(QString html READ html WRITE setHtml)
+
+ Q_PROPERTY(int idealWidth READ idealWidth WRITE setIdealWidth NOTIFY idealWidthChanged)
+ Q_PROPERTY(int idealHeight READ idealHeight WRITE setIdealHeight NOTIFY idealHeightChanged)
+ Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+
+ Q_PROPERTY(bool interactive READ interactive WRITE setInteractive NOTIFY interactiveChanged)
+
+ Q_PROPERTY(int cacheSize READ cacheSize WRITE setCacheSize)
+
+ Q_PROPERTY(QObject* reload READ reloadAction)
+ Q_PROPERTY(QObject* back READ backAction)
+ Q_PROPERTY(QObject* forward READ forwardAction)
+ Q_PROPERTY(QObject* stop READ stopAction)
+
+ Q_PROPERTY(QObject* settings READ settingsObject)
+
+public:
+ QFxWebView(QFxItem *parent=0);
+ ~QFxWebView();
+
+ QString url() const;
+ void setUrl(const QString &);
+
+ QString title() const;
+
+ QPixmap icon() const;
+
+ qreal textSizeMultiplier() const;
+ void setTextSizeMultiplier(qreal);
+
+ bool interactive() const;
+ void setInteractive(bool);
+
+ int cacheSize() const;
+ void setCacheSize(int pixels);
+
+ int mouseX() const;
+ int mouseY() const;
+
+ int idealWidth() const;
+ void setIdealWidth(int);
+ int idealHeight() const;
+ void setIdealHeight(int);
+
+
+ qreal progress() const;
+
+ QAction *reloadAction() const;
+ QAction *backAction() const;
+ QAction *forwardAction() const;
+ QAction *stopAction() const;
+
+ virtual void dump(int depth);
+ virtual QString propertyInfo() const;
+
+ QWebPage *page() const;
+ void setPage(QWebPage *page);
+
+ void load(const QNetworkRequest &request,
+ QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
+ const QByteArray &body = QByteArray());
+
+ QString html() const;
+
+ void setHtml(const QString &html, const QUrl &baseUrl = QUrl());
+ void setContent(const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl());
+
+ QWebHistory *history() const;
+ QWebSettings *settings() const;
+ QObject *settingsObject() const;
+
+ QString status() const;
+
+Q_SIGNALS:
+ void idealWidthChanged();
+ void idealHeightChanged();
+ void urlChanged();
+ void interactiveChanged();
+ void progressChanged();
+ void titleChanged(const QString&);
+ void iconChanged();
+ void statusChanged();
+
+ void loadStarted();
+ void loadFinished();
+ void loadFailed();
+
+ void singleClick();
+ void doubleClick();
+
+private Q_SLOTS:
+ void updateCacheForVisibility();
+ void expandToWebPage();
+ void paintPage(const QRect&);
+ void doLoadProgress(int p);
+ void doLoadFinished(bool ok);
+ void setStatusBarMessage(const QString&);
+
+protected:
+ QFxWebView(QFxWebViewPrivate &dd, QFxItem *parent);
+
+ void drawContents(QPainter *, const QRect &);
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ void keyPressEvent(QKeyEvent* event);
+ void keyReleaseEvent(QKeyEvent* event);
+ void timerEvent(QTimerEvent *event);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+private:
+ void init();
+ virtual void componentComplete();
+ Q_DISABLE_COPY(QFxWebView)
+ Q_DECLARE_PRIVATE(QFxWebView)
+};
+QML_DECLARE_TYPE(QFxWebView);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/fx/qfxwidgetcontainer.cpp b/src/declarative/fx/qfxwidgetcontainer.cpp
new file mode 100644
index 0000000..fccdad1
--- /dev/null
+++ b/src/declarative/fx/qfxwidgetcontainer.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxwidgetcontainer.h"
+#include <qsimplecanvas.h>
+#include <qgraphicswidget.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass WidgetContainer QFxWidgetContainer
+ \brief The WidgetContainer element allows you to add QGraphicsWidgets into Fluid UI elements.
+*/
+
+/*!
+ \internal
+ \class QFxWidgetContainer
+ \brief The QFxWidgetContainer class allows you to add QGraphicsWidgets into Fluid UI applications.
+*/
+
+QML_DEFINE_TYPE(QFxWidgetContainer, WidgetContainer);
+
+QFxWidgetContainer::QFxWidgetContainer(QFxItem *parent)
+: QFxItem(parent), _graphicsWidget(0)
+{
+}
+
+QFxWidgetContainer::~QFxWidgetContainer()
+{
+}
+
+QGraphicsWidget *QFxWidgetContainer::graphicsWidget() const
+{
+ return _graphicsWidget;
+}
+
+/*!
+ \qmlproperty QGraphicsWidget QFxWidgetContainer::graphicsWidget
+ The QGraphicsWidget associated with this element.
+*/
+void QFxWidgetContainer::setGraphicsWidget(QGraphicsWidget *widget)
+{
+ if (widget == _graphicsWidget)
+ return;
+
+ _graphicsWidget = widget;
+
+ QSimpleCanvas *c = canvas();
+ if (!c)
+ return;
+
+ if (c->canvasMode() != QSimpleCanvas::GraphicsView) {
+ qWarning("QFxWidgetContainer: Cannot add a widget to a non-graphicsview canvas. You might need to set QFX_USE_GRAPHICSVIEW=1");
+ return;
+ }
+
+ QGraphicsItem *item = (QGraphicsItem *)(*this);
+ _graphicsWidget->setParentItem(item);
+}
+
+void QFxWidgetContainer::canvasChanged()
+{
+ if (_graphicsWidget) {
+ QGraphicsWidget *w = _graphicsWidget;
+ _graphicsWidget = 0;
+ setGraphicsWidget(w);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxwidgetcontainer.h b/src/declarative/fx/qfxwidgetcontainer.h
new file mode 100644
index 0000000..65e4352
--- /dev/null
+++ b/src/declarative/fx/qfxwidgetcontainer.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXWIDGETCONTAINER_H
+#define QFXWIDGETCONTAINER_H
+
+#include <QtDeclarative/qfxitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsWidget;
+
+class Q_DECLARATIVE_EXPORT QFxWidgetContainer : public QFxItem
+{
+ Q_OBJECT
+
+ Q_CLASSINFO("DefaultProperty", "graphicsWidget")
+ Q_PROPERTY(QGraphicsWidget *graphicsWidget READ graphicsWidget WRITE setGraphicsWidget)
+
+public:
+ QFxWidgetContainer(QFxItem *parent = 0);
+ ~QFxWidgetContainer();
+
+ QGraphicsWidget *graphicsWidget() const;
+ void setGraphicsWidget(QGraphicsWidget *);
+
+protected:
+ virtual void canvasChanged();
+
+private:
+ QGraphicsWidget *_graphicsWidget;
+};
+QML_DECLARE_TYPE(QFxWidgetContainer);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXGRAPHICSWIDGET_H
diff --git a/src/declarative/opengl/glbasicshaders.cpp b/src/declarative/opengl/glbasicshaders.cpp
new file mode 100644
index 0000000..f546c0b
--- /dev/null
+++ b/src/declarative/opengl/glbasicshaders.cpp
@@ -0,0 +1,707 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "glbasicshaders.h"
+#include <QDebug>
+#include <QColor>
+
+
+QT_BEGIN_NAMESPACE
+SingleTextureVertexOpacityShader::SingleTextureVertexOpacityShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute lowp float myOpacity;\
+ attribute mediump vec4 myUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ varying lowp float myFragOpacity;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ myFragOpacity = myOpacity;\
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ varying mediump vec2 myTexCoord;\
+ varying lowp float myFragOpacity;\
+ void main(void)\
+ {\
+ mediump vec4 frag = texture2D(sampler2d,myTexCoord);\
+ gl_FragColor = vec4(frag.rgb, frag.a * myFragOpacity);\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+ bindAttributeLocation("myOpacity", OpacityCoords);
+}
+
+bool SingleTextureVertexOpacityShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ enable();
+ setUniformValue("sampler2d", 0);
+ disable();
+ return true;
+}
+
+void SingleTextureVertexOpacityShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+BlurTextureShader::BlurTextureShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute mediump vec4 myUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ }"
+ );
+
+#if 0
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ uniform bool horizontal; \
+ uniform mediump float blurStep; \
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ mediump vec4 accum = vec4(0, 0, 0, 0); \
+ mediump vec2 offset; \
+ if (horizontal) \
+ offset = vec2(blurStep, 0); \
+ else \
+ offset = vec2(0, blurStep); \
+ accum += texture2D(sampler2d, myTexCoord + 2.0 * offset); \
+ accum += 2.0 * texture2D(sampler2d, myTexCoord + 1.0 * offset); \
+ accum += 4.0 * texture2D(sampler2d, myTexCoord + 0.0 * offset); \
+ accum += 2.0 * texture2D(sampler2d, myTexCoord - 1.0 * offset); \
+ accum += texture2D(sampler2d, myTexCoord - 2.0 * offset); \
+ gl_FragColor = accum / 10.0; \
+ }"
+ );
+#else
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ uniform bool horizontal; \
+ uniform mediump float blurStep; \
+ uniform int blurSteps; \
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ mediump vec4 accum = vec4(0, 0, 0, 0); \
+ mediump vec2 offset; \
+ if (horizontal) \
+ offset = vec2(blurStep, 0); \
+ else \
+ offset = vec2(0, blurStep); \
+ mediump float sum = 0.0; \
+ for (int ii = 0; ii < blurSteps; ++ii) { \
+ mediump float frac = float(blurSteps - ii) / float(blurSteps); \
+ mediump vec2 coord = myTexCoord + -float(ii) * offset; \
+ if (coord.x >= 0.0 && coord.y >= 0.0 && coord.y <= 1.0 && coord.x <=1.0) \
+ accum += texture2D(sampler2d, coord) * frac; \
+ sum += frac; \
+ } \
+ for (int ii = 1; ii < blurSteps; ++ii) { \
+ mediump float frac = float(blurSteps - ii) / float(blurSteps); \
+ mediump vec2 coord = myTexCoord + float(ii) * offset; \
+ if (coord.x <= 1.0 && coord.y <= 1.0 && coord.x >= 0.0 && coord.y >= 0.0) \
+ accum += texture2D(sampler2d, coord) * frac; \
+ sum += frac; \
+ } \
+ gl_FragColor = accum / sum; \
+ }"
+ );
+#endif
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+}
+
+bool BlurTextureShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ mode = uniformLocation("horizontal");
+ step = uniformLocation("blurStep");
+ steps = uniformLocation("blurSteps");
+ enable();
+ setUniformValue("sampler2d", 0);
+ disable();
+ return true;
+}
+
+void BlurTextureShader::setStep(float f)
+{
+ setUniformValue(step, f);
+}
+
+void BlurTextureShader::setSteps(int s)
+{
+ setUniformValue(steps, s);
+}
+
+void BlurTextureShader::setMode(Mode m)
+{
+ if (m == Horizontal)
+ setUniformValue(mode, 1);
+ else
+ setUniformValue(mode, 0);
+}
+
+void BlurTextureShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+DualTextureBlendShader::DualTextureBlendShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute mediump vec4 myUV;\
+ attribute mediump vec4 myBlendUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ varying mediump vec2 myBlendTexCoord;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ myBlendTexCoord = myBlendUV.st;\
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ uniform sampler2D sampler2dBlend;\
+ uniform lowp float myOpacity;\
+ uniform lowp float myBlend; \
+ varying mediump vec2 myTexCoord;\
+ varying mediump vec2 myBlendTexCoord;\
+ void main(void)\
+ {\
+ mediump vec4 tex = texture2D(sampler2d,myTexCoord);\
+ mediump vec4 blendtex = texture2D(sampler2dBlend, myBlendTexCoord);\
+ gl_FragColor = mix(tex, blendtex, myBlend) * myOpacity; \
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+ bindAttributeLocation("myBlendUV", BlendTextureCoords);
+}
+
+bool DualTextureBlendShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ opacity = uniformLocation("myOpacity");
+ blend = uniformLocation("myBlend");
+ enable();
+ setUniformValue("sampler2d", 0);
+ setUniformValue("sampler2dBlend", 1);
+ disable();
+ return true;
+}
+
+void DualTextureBlendShader::setOpacity(GLfloat o)
+{
+ setUniformValue(opacity, o);
+}
+
+void DualTextureBlendShader::setBlend(GLfloat b)
+{
+ setUniformValue(blend, b);
+}
+
+void DualTextureBlendShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+DualTextureAddShader::DualTextureAddShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute mediump vec4 myUV;\
+ attribute mediump vec4 myAddUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ varying mediump vec2 myAddTexCoord;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ myAddTexCoord = myAddUV.st;\
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ uniform sampler2D sampler2dAdd;\
+ uniform lowp float myOpacity;\
+ varying mediump vec2 myTexCoord;\
+ varying mediump vec2 myAddTexCoord;\
+ void main(void)\
+ {\
+ mediump vec4 tex = texture2D(sampler2d,myTexCoord);\
+ mediump vec4 addtex = texture2D(sampler2dAdd, myAddTexCoord);\
+ tex = tex + vec4(addtex.rgb * addtex.a * tex.a, 0); \
+ tex = min(tex, vec4(1, 1, 1, 1)); \
+ gl_FragColor = vec4(tex.rgb, tex.a) * myOpacity;\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+ bindAttributeLocation("myAddUV", AddTextureCoords);
+}
+
+void DualTextureAddShader::setOpacity(GLfloat f)
+{
+ setUniformValue(opacity, f);
+}
+
+void DualTextureAddShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+bool DualTextureAddShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ opacity = uniformLocation("myOpacity");
+ enable();
+ setUniformValue("sampler2d", 0);
+ setUniformValue("sampler2dAdd", 1);
+ disable();
+ return true;
+}
+
+SingleTextureShader::SingleTextureShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute mediump vec4 myUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ gl_FragColor = texture2D(sampler2d,myTexCoord);\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+}
+
+bool SingleTextureShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ enable();
+ setUniformValue("sampler2d", 0);
+ disable();
+ return true;
+}
+
+void SingleTextureShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+ConstantColorShader::ConstantColorShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ uniform mediump mat4 myPMVMatrix;\
+ attribute highp vec4 myVertex;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex; \
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform lowp vec4 myColor;\
+ void main(void)\
+ {\
+ gl_FragColor = myColor;\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+}
+
+void ConstantColorShader::setColor(const QColor &c)
+{
+ setUniformValue(color, c);
+}
+
+void ConstantColorShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+bool ConstantColorShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ color = uniformLocation("myColor");
+ return true;
+}
+
+ColorShader::ColorShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ uniform mediump mat4 myPMVMatrix;\
+ attribute highp vec4 myVertex;\
+ attribute lowp vec4 myColors;\
+ varying lowp vec4 myColor;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex; \
+ myColor = myColors; \
+ }"
+ );
+
+ frag.setSourceCode("\
+ varying lowp vec4 myColor;\
+ void main(void)\
+ {\
+ gl_FragColor = myColor;\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myColors", Colors);
+}
+
+void ColorShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+bool ColorShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ return true;
+}
+
+class GLBasicShadersPrivate
+{
+public:
+ GLBasicShadersPrivate();
+ ~GLBasicShadersPrivate();
+
+ BlurTextureShader *blurTexture;
+ SingleTextureShader *singleTexture;
+ SingleTextureOpacityShader *singleTextureOpacity;
+ DualTextureAddShader *dualTextureAdd;
+ SingleTextureShadowShader *singleTextureShadow;
+ SingleTextureVertexOpacityShader *singleTextureVertexOpacity;
+ ConstantColorShader *constantColor;
+ ColorShader *color;
+};
+
+GLBasicShadersPrivate::GLBasicShadersPrivate()
+: blurTexture(0), singleTexture(0), singleTextureOpacity(0),
+ dualTextureAdd(0), singleTextureShadow(0), singleTextureVertexOpacity(0),
+ constantColor(0), color(0)
+{
+}
+
+GLBasicShadersPrivate::~GLBasicShadersPrivate()
+{
+ delete blurTexture;
+ delete singleTexture;
+ delete singleTextureOpacity;
+ delete dualTextureAdd;
+ delete singleTextureVertexOpacity;
+ delete singleTextureShadow;
+ delete constantColor;
+ delete color;
+}
+
+GLBasicShaders::GLBasicShaders()
+: d(new GLBasicShadersPrivate)
+{
+}
+
+GLBasicShaders::~GLBasicShaders()
+{
+ delete d;
+}
+
+BlurTextureShader *GLBasicShaders::blurTexture()
+{
+ if (!d->blurTexture) d->blurTexture = new BlurTextureShader();
+ return d->blurTexture;
+}
+
+SingleTextureShader *GLBasicShaders::singleTexture()
+{
+ if (!d->singleTexture) d->singleTexture = new SingleTextureShader();
+ return d->singleTexture;
+}
+
+SingleTextureOpacityShader *GLBasicShaders::singleTextureOpacity()
+{
+ if (!d->singleTextureOpacity) d->singleTextureOpacity = new SingleTextureOpacityShader();
+ return d->singleTextureOpacity;
+}
+
+DualTextureAddShader *GLBasicShaders::dualTextureAdd()
+{
+ if (!d->dualTextureAdd) d->dualTextureAdd = new DualTextureAddShader();
+ return d->dualTextureAdd;
+}
+
+SingleTextureVertexOpacityShader *GLBasicShaders::singleTextureVertexOpacity()
+{
+ if (!d->singleTextureVertexOpacity) d->singleTextureVertexOpacity = new SingleTextureVertexOpacityShader();
+ return d->singleTextureVertexOpacity;
+}
+
+SingleTextureShadowShader *GLBasicShaders::singleTextureShadow()
+{
+ if (!d->singleTextureShadow) d->singleTextureShadow = new SingleTextureShadowShader();
+ return d->singleTextureShadow;
+}
+
+ConstantColorShader *GLBasicShaders::constantColor()
+{
+ if (!d->constantColor) d->constantColor = new ConstantColorShader();
+ return d->constantColor;
+}
+
+ColorShader *GLBasicShaders::color()
+{
+ if (!d->color) d->color = new ColorShader();
+ return d->color;
+}
+
+SingleTextureOpacityShader::SingleTextureOpacityShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute mediump vec4 myUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ uniform lowp float myOpacity;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ mediump vec4 tex = texture2D(sampler2d,myTexCoord);\
+ gl_FragColor = vec4(tex.rgb, myOpacity * tex.a);\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+}
+
+bool SingleTextureOpacityShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ opacity = uniformLocation("myOpacity");
+ enable();
+ setUniformValue("sampler2d", 0);
+ disable();
+ return true;
+}
+
+void SingleTextureOpacityShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+void SingleTextureOpacityShader::setOpacity(GLfloat f)
+{
+ setUniformValue(opacity, f);
+}
+
+SingleTextureShadowShader::SingleTextureShadowShader()
+{
+ QGLShader vert(QGLShader::VertexShader);
+ QGLShader frag(QGLShader::FragmentShader);
+
+ vert.setSourceCode("\
+ attribute highp vec4 myVertex;\
+ attribute mediump vec4 myUV;\
+ uniform mediump mat4 myPMVMatrix;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ gl_Position = myPMVMatrix * myVertex;\
+ myTexCoord = myUV.st;\
+ }"
+ );
+
+ frag.setSourceCode("\
+ uniform sampler2D sampler2d;\
+ uniform lowp float myOpacity;\
+ varying mediump vec2 myTexCoord;\
+ void main(void)\
+ {\
+ mediump vec4 tex = texture2D(sampler2d,myTexCoord);\
+ gl_FragColor = vec4(0, 0, 0, myOpacity * tex.a * .75);\
+ }"
+ );
+
+ addShader(&vert);
+ addShader(&frag);
+
+ bindAttributeLocation("myVertex", Vertices);
+ bindAttributeLocation("myUV", TextureCoords);
+}
+
+bool SingleTextureShadowShader::link()
+{
+ if (!QGLShaderProgram::link())
+ return false;
+ transform = uniformLocation("myPMVMatrix");
+ opacity = uniformLocation("myOpacity");
+ enable();
+ setUniformValue("sampler2d", 0);
+ disable();
+ return true;
+}
+
+void SingleTextureShadowShader::setTransform(const QMatrix4x4 &matrix)
+{
+ setUniformValue(transform, matrix);
+}
+
+void SingleTextureShadowShader::setOpacity(GLfloat f)
+{
+ setUniformValue(opacity, f);
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/opengl/glbasicshaders.h b/src/declarative/opengl/glbasicshaders.h
new file mode 100644
index 0000000..7d358d8
--- /dev/null
+++ b/src/declarative/opengl/glbasicshaders.h
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _GLBASICSHADERS_H_
+#define _GLBASICSHADERS_H_
+
+#include <QtOpenGL/qglshaderprogram.h>
+#include <QtGui/qmatrix4x4.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class BlurTextureShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ BlurTextureShader();
+
+ enum { Vertices = 0,
+ TextureCoords = 1 };
+
+ enum Mode { Horizontal, Vertical };
+ void setMode(Mode);
+ void setStep(float);
+ void setSteps(int);
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint mode;
+ GLint step;
+ GLint steps;
+ GLint transform;
+};
+
+class SingleTextureShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ SingleTextureShader();
+
+ enum { Vertices = 0,
+ TextureCoords = 1 };
+
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+};
+
+class DualTextureBlendShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ DualTextureBlendShader();
+ enum { Vertices = 0,
+ TextureCoords = 1,
+ BlendTextureCoords = 2 };
+
+ void setOpacity(GLfloat);
+ void setBlend(GLfloat);
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+ GLint opacity;
+ GLint blend;
+};
+
+class DualTextureAddShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ DualTextureAddShader();
+ enum { Vertices = 0,
+ TextureCoords = 1,
+ AddTextureCoords = 2 };
+
+ void setOpacity(GLfloat);
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+ GLint opacity;
+};
+
+class SingleTextureOpacityShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ SingleTextureOpacityShader();
+
+ enum { Vertices = 0,
+ TextureCoords = 1 };
+
+ void setOpacity(GLfloat);
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+ GLint opacity;
+};
+
+class SingleTextureVertexOpacityShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ SingleTextureVertexOpacityShader();
+
+ enum { Vertices = 0,
+ TextureCoords = 1,
+ OpacityCoords = 2 };
+
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+};
+
+
+class SingleTextureShadowShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ SingleTextureShadowShader();
+
+ enum { Vertices = 0,
+ TextureCoords = 1 };
+
+ void setOpacity(GLfloat);
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+ GLint opacity;
+};
+
+
+class QColor;
+class ConstantColorShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ ConstantColorShader();
+
+ enum { Vertices = 0 };
+
+ void setColor(const QColor &);
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+ GLint color;
+};
+
+class ColorShader : public QGLShaderProgram
+{
+ Q_OBJECT
+public:
+ ColorShader();
+
+ enum { Vertices = 0, Colors = 1 };
+
+ void setTransform(const QMatrix4x4 &);
+ virtual bool link();
+
+private:
+ GLint transform;
+};
+
+class GLBasicShadersPrivate;
+class GLBasicShaders
+{
+public:
+ GLBasicShaders();
+ virtual ~GLBasicShaders();
+
+ BlurTextureShader *blurTexture();
+ SingleTextureShader *singleTexture();
+ SingleTextureOpacityShader *singleTextureOpacity();
+ DualTextureAddShader *dualTextureAdd();
+ SingleTextureVertexOpacityShader *singleTextureVertexOpacity();
+ SingleTextureShadowShader *singleTextureShadow();
+ ConstantColorShader *constantColor();
+ ColorShader *color();
+
+private:
+ GLBasicShadersPrivate *d;
+};
+
+#endif // _GLBASICSHADERS_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/opengl/glheaders.h b/src/declarative/opengl/glheaders.h
new file mode 100644
index 0000000..f0f6a55
--- /dev/null
+++ b/src/declarative/opengl/glheaders.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _GLHEADERS_H_
+#define _GLHEADERS_H_
+
+#include <qfxglobal.h>
+#define GL_GLEXT_PROTOTYPES 1
+#include <QtOpenGL/qgl.h>
+
+#endif // _GLHEADERS_H_
diff --git a/src/declarative/opengl/glsave.cpp b/src/declarative/opengl/glsave.cpp
new file mode 100644
index 0000000..125e81b
--- /dev/null
+++ b/src/declarative/opengl/glsave.cpp
@@ -0,0 +1 @@
+#include "glsave.h"
diff --git a/src/declarative/opengl/glsave.h b/src/declarative/opengl/glsave.h
new file mode 100644
index 0000000..cca3d3c
--- /dev/null
+++ b/src/declarative/opengl/glsave.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _GLSAVE_H_
+#define _GLSAVE_H_
+
+#include <qglobal.h>
+#include <qfxglobal.h>
+#include <QRect>
+#include "glheaders.h"
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class GLSaveViewport
+{
+public:
+ GLSaveViewport()
+ {
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ }
+
+ ~GLSaveViewport()
+ {
+ glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
+ }
+
+private:
+ Q_DISABLE_COPY(GLSaveViewport);
+ GLint viewport[4];
+};
+
+class GLSaveScissor
+{
+public:
+ GLSaveScissor()
+ {
+ enabled = glIsEnabled(GL_SCISSOR_TEST);
+ glGetIntegerv(GL_SCISSOR_BOX, box);
+ }
+
+ ~GLSaveScissor()
+ {
+ if (enabled)
+ glEnable(GL_SCISSOR_TEST);
+ else
+ glDisable(GL_SCISSOR_TEST);
+ glScissor(box[0], box[1], box[2], box[3]);
+ }
+
+ bool wasEnabled() const
+ {
+ return enabled == GL_TRUE;
+ }
+
+ QRect rect() const
+ {
+ return QRect(box[0], box[1], box[2], box[3]);
+ }
+
+private:
+ Q_DISABLE_COPY(GLSaveScissor);
+ GLint box[4];
+ GLboolean enabled;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // _GLSAVE_H_
diff --git a/src/declarative/opengl/gltexture.cpp b/src/declarative/opengl/gltexture.cpp
new file mode 100644
index 0000000..199b362
--- /dev/null
+++ b/src/declarative/opengl/gltexture.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gltexture.h"
+#include <QImage>
+
+
+QT_BEGIN_NAMESPACE
+/*!
+ \internal
+ \class GLTexture
+ \brief The GLTexture class simplifies the use of OpenGL textures.
+*/
+
+// Copied from QGLWidget::convertToGLFormat
+static QImage QGLWidget_convertToGLFormat(const QImage& img)
+{
+ QImage res = img.convertToFormat(QImage::Format_ARGB32);
+ res = res.mirrored();
+
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ // Qt has ARGB; OpenGL wants RGBA
+ for (int i=0; i < res.height(); i++) {
+ uint *p = (uint*)res.scanLine(i);
+ uint *end = p + res.width();
+ while (p < end) {
+ *p = (*p << 8) | ((*p >> 24) & 0xFF);
+ p++;
+ }
+ }
+ }
+ else {
+ // Qt has ARGB; OpenGL wants ABGR (i.e. RGBA backwards)
+ res = res.rgbSwapped();
+ }
+ return res;
+}
+class GLTexturePrivate
+{
+public:
+ GLTexturePrivate(GLTexture *_q)
+ : q(_q), texture(0), width(0), height(0),
+ horizWrap(GLTexture::Repeat), vertWrap(GLTexture::Repeat),
+ minFilter(GLTexture::Linear), magFilter(GLTexture::Linear)
+ {
+ }
+
+ GLTexture *q;
+ GLuint texture;
+ int width;
+ int height;
+ GLTexture::WrapMode horizWrap;
+ GLTexture::WrapMode vertWrap;
+ GLTexture::FilterMode minFilter;
+ GLTexture::FilterMode magFilter;
+
+ void genTexture();
+};
+
+void GLTexturePrivate::genTexture()
+{
+ if (texture)
+ return;
+
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
+ q->setHorizontalWrap(horizWrap);
+ q->setVerticalWrap(vertWrap);
+}
+
+GLTexture::GLTexture()
+: d(new GLTexturePrivate(this))
+{
+}
+
+GLTexture::GLTexture(const QString &file)
+: d(new GLTexturePrivate(this))
+{
+ QImage img(file);
+ if (!img.isNull())
+ setImage(img);
+}
+
+GLTexture::GLTexture(const QImage &img)
+: d(new GLTexturePrivate(this))
+{
+ setImage(img);
+}
+
+GLTexture::~GLTexture()
+{
+ if (d->texture)
+ glDeleteTextures(1, &d->texture);
+ delete d;
+ d = 0;
+}
+
+bool GLTexture::isNull() const
+{
+ return d->texture == 0;
+}
+
+void GLTexture::clear()
+{
+ if (d->texture) {
+ glDeleteTextures(1, &d->texture);
+ d->texture = 0;
+ d->width = 0;
+ d->height = 0;
+ }
+}
+
+static inline int npot(int size)
+{
+ size--;
+ size |= size >> 1;
+ size |= size >> 2;
+ size |= size >> 4;
+ size |= size >> 8;
+ size |= size >> 16;
+ size++;
+ return size;
+}
+
+/*!
+ Set the texture to \a img. If the texture has already been created (either
+ by explicitly setting the size, or by previously setting an image), it will
+ be destroyed and a new texture created with \a img's contents and size.
+ */
+void GLTexture::setImage(const QImage &img)
+{
+ if (img.isNull())
+ return;
+
+ d->genTexture();
+
+ //QImage dataImage = img.scaled(npot(img.width()), npot(img.height()), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ QImage dataImage = QGLWidget_convertToGLFormat(img);
+
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dataImage.width(),
+ dataImage.height(), 0,
+ (dataImage.format() == QImage::Format_ARGB32)?GL_RGBA:GL_RGB,
+ GL_UNSIGNED_BYTE, dataImage.bits());
+ d->width = dataImage.width();
+ d->height = dataImage.height();
+
+#if 0
+ glGenerateMipmap(GL_TEXTURE_2D);
+ int e = glGetError();
+ if (d->magFilter == Linear)
+ setMagFilter(MipmapLinear);
+ if (d->minFilter == Linear)
+ setMinFilter((GLTexture::FilterMode)GL_LINEAR_MIPMAP_LINEAR);
+#endif
+}
+
+void GLTexture::copyImage(const QImage &img, const QPoint &point,
+ const QRect &srcRect)
+{
+ qFatal("Not implemented");
+ Q_UNUSED(img);
+ Q_UNUSED(point);
+ Q_UNUSED(srcRect);
+}
+
+QSize GLTexture::size() const
+{
+ return QSize(d->width, d->height);
+}
+
+int GLTexture::width() const
+{
+ return d->width;
+}
+
+int GLTexture::height() const
+{
+ return d->height;
+}
+
+/*!
+ Sets the \a size of the texture. This will destroy the current contents of
+ the texture. If an image has been assigned, it will need to be reassigned
+ using either setImage() or copyImage().
+
+ If size is invalid (width or height is less than or equal to 0) the texture
+ will be destroyed. This is equivalent to calling clear().
+*/
+void GLTexture::setSize(const QSize &size)
+{
+ if (size.width() <= 0 || size.height() <= 0) {
+ clear();
+ return;
+ }
+
+ d->genTexture();
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ d->width = size.width();
+ d->height = size.height();
+}
+
+GLTexture::WrapMode GLTexture::horizontalWrap() const
+{
+ return d->horizWrap;
+}
+
+GLTexture::WrapMode GLTexture::verticalWrap() const
+{
+ return d->vertWrap;
+}
+
+void GLTexture::setHorizontalWrap(WrapMode mode)
+{
+ d->horizWrap = mode;
+ if (d->texture) {
+ GLint last;
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &last);
+ if (GLuint(last) != d->texture)
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode);
+ if (GLuint(last) != d->texture)
+ glBindTexture(GL_TEXTURE_2D, last);
+ }
+}
+
+/*!
+ Set the veritcal wrap mode to \a mode.
+ */
+void GLTexture::setVerticalWrap(WrapMode mode)
+{
+ d->vertWrap = mode;
+ if (d->texture) {
+ GLint last;
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &last);
+ if (GLuint(last) != d->texture)
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode);
+ if (GLuint(last) != d->texture)
+ glBindTexture(GL_TEXTURE_2D, last);
+ }
+}
+
+GLTexture::FilterMode GLTexture::minFilter() const
+{
+ return d->minFilter;
+}
+
+GLTexture::FilterMode GLTexture::magFilter() const
+{
+ return d->magFilter;
+}
+
+void GLTexture::setMinFilter(FilterMode f)
+{
+ if (d->minFilter == f)
+ return;
+ d->minFilter = f;
+ if (d->texture) {
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, d->minFilter);
+ }
+}
+
+void GLTexture::setMagFilter(FilterMode f)
+{
+ if (d->magFilter == f)
+ return;
+ d->magFilter = f;
+ if (d->texture) {
+ glBindTexture(GL_TEXTURE_2D, d->texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, d->magFilter);
+ }
+}
+
+GLuint GLTexture::texture() const
+{
+ return d->texture;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/opengl/gltexture.h b/src/declarative/opengl/gltexture.h
new file mode 100644
index 0000000..f920b60
--- /dev/null
+++ b/src/declarative/opengl/gltexture.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _GLTEXTURE_H_
+#define _GLTEXTURE_H_
+
+#include <qfxglobal.h>
+
+#include <QRect>
+#include <QPoint>
+#include "glheaders.h"
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QImage;
+class GLTexturePrivate;
+class Q_DECLARATIVE_EXPORT GLTexture
+{
+public:
+ GLTexture();
+ GLTexture(const QString &file);
+ GLTexture(const QImage &img);
+ virtual ~GLTexture();
+
+ bool isNull() const;
+ void clear();
+
+ void setImage(const QImage &);
+ void copyImage(const QImage &, const QPoint & = QPoint(0, 0), const QRect & = QRect());
+
+ int width() const;
+ int height() const;
+ QSize size() const;
+ void setSize(const QSize &);
+
+ enum WrapMode {
+ Repeat = GL_REPEAT,
+ ClampToEdge = GL_CLAMP_TO_EDGE,
+#if defined(QFX_RENDER_OPENGL2)
+ MirroredRepeat = GL_MIRRORED_REPEAT,
+#else
+ MirroredRepeat = Repeat
+#endif
+ };
+
+ WrapMode horizontalWrap() const;
+ WrapMode verticalWrap() const;
+ void setHorizontalWrap(WrapMode);
+ void setVerticalWrap(WrapMode);
+
+ enum FilterMode {
+ Nearest = GL_NEAREST,
+ Linear = GL_LINEAR,
+ MipmapLinear = GL_LINEAR_MIPMAP_LINEAR
+ };
+
+ FilterMode minFilter() const;
+ FilterMode magFilter() const;
+ void setMinFilter(FilterMode);
+ void setMagFilter(FilterMode);
+
+ GLuint texture() const;
+private:
+ Q_DISABLE_COPY(GLTexture);
+ GLTexturePrivate *d;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // _GLTEXTURE_H_
diff --git a/src/declarative/opengl/opengl.pri b/src/declarative/opengl/opengl.pri
new file mode 100644
index 0000000..c9ccefb
--- /dev/null
+++ b/src/declarative/opengl/opengl.pri
@@ -0,0 +1,20 @@
+DEPENDPATH += opengl
+INCLUDEPATH += opengl
+INCLUDEPATH += $$QMAKE_INCDIR_OPENGL
+QT += opengl
+
+contains(QT_CONFIG, opengles1) {
+ SOURCES += gltexture.cpp \
+ glsave.cpp
+
+ HEADERS += gltexture.h \
+ glsave.h
+} else:contains(QT_CONFIG, opengles2) {
+ SOURCES += gltexture.cpp \
+ glbasicshaders.cpp \
+ glsave.cpp
+
+ HEADERS += gltexture.h \
+ glbasicshaders.h \
+ glsave.h
+}
diff --git a/src/declarative/qml/parser/javascript.g b/src/declarative/qml/parser/javascript.g
new file mode 100644
index 0000000..48e8244
--- /dev/null
+++ b/src/declarative/qml/parser/javascript.g
@@ -0,0 +1,2809 @@
+----------------------------------------------------------------------------
+--
+-- Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+-- Contact: Qt Software Information (qt-info@nokia.com)
+--
+-- This file is part of the QtScript module of the Qt Toolkit.
+--
+-- $QT_BEGIN_LICENSE:LGPL$
+-- No Commercial Usage
+-- This file contains pre-release code and may not be distributed.
+-- You may use this file in accordance with the terms and conditions
+-- contained in the either Technology Preview License Agreement or the
+-- Beta Release License Agreement.
+--
+-- GNU Lesser General Public License Usage
+-- Alternatively, this file may be used under the terms of the GNU Lesser
+-- General Public License version 2.1 as published by the Free Software
+-- Foundation and appearing in the file LICENSE.LGPL included in the
+-- packaging of this file. Please review the following information to
+-- ensure the GNU Lesser General Public License version 2.1 requirements
+-- will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+--
+-- In addition, as a special exception, Nokia gives you certain
+-- additional rights. These rights are described in the Nokia Qt LGPL
+-- Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+-- package.
+--
+-- GNU General Public License Usage
+-- Alternatively, this file may be used under the terms of the GNU
+-- General Public License version 3.0 as published by the Free Software
+-- Foundation and appearing in the file LICENSE.GPL included in the
+-- packaging of this file. Please review the following information to
+-- ensure the GNU General Public License version 3.0 requirements will be
+-- met: http://www.gnu.org/copyleft/gpl.html.
+--
+-- If you are unsure which license is appropriate for your use, please
+-- contact the sales department at qt-sales@nokia.com.
+-- $QT_END_LICENSE$
+--
+-- This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+-- WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+--
+----------------------------------------------------------------------------
+
+%parser JavaScriptGrammar
+%decl javascriptparser_p.h
+%impl javascriptparser.cpp
+%expect 2
+%expect-rr 1
+
+%token T_AND "&" T_AND_AND "&&" T_AND_EQ "&="
+%token T_BREAK "break" T_CASE "case" T_CATCH "catch"
+%token T_COLON ":" T_COMMA ";" T_CONTINUE "continue"
+%token T_DEFAULT "default" T_DELETE "delete" T_DIVIDE_ "/"
+%token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "."
+%token T_ELSE "else" T_EQ "=" T_EQ_EQ "=="
+%token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for"
+%token T_FUNCTION "function" T_GE ">=" T_GT ">"
+%token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>"
+%token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if"
+%token T_IN "in" T_INSTANCEOF "instanceof" T_LBRACE "{"
+%token T_LBRACKET "[" T_LE "<=" T_LPAREN "("
+%token T_LT "<" T_LT_LT "<<" T_LT_LT_EQ "<<="
+%token T_MINUS "-" T_MINUS_EQ "-=" T_MINUS_MINUS "--"
+%token T_NEW "new" T_NOT "!" T_NOT_EQ "!="
+%token T_NOT_EQ_EQ "!==" T_NUMERIC_LITERAL "numeric literal" T_OR "|"
+%token T_OR_EQ "|=" T_OR_OR "||" T_PLUS "+"
+%token T_PLUS_EQ "+=" T_PLUS_PLUS "++" T_QUESTION "?"
+%token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%"
+%token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")"
+%token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*"
+%token T_STAR_EQ "*=" T_STRING_LITERAL "string literal"
+%token T_PROPERTY "property" T_SIGNAL "signal"
+%token T_SWITCH "switch" T_THIS "this" T_THROW "throw"
+%token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof"
+%token T_VAR "var" T_VOID "void" T_WHILE "while"
+%token T_WITH "with" T_XOR "^" T_XOR_EQ "^="
+%token T_NULL "null" T_TRUE "true" T_FALSE "false"
+%token T_CONST "const"
+%token T_DEBUGGER "debugger"
+%token T_RESERVED_WORD "reserved word"
+%token T_MULTILINE_STRING_LITERAL "multiline string literal"
+
+--- context keywords.
+%token T_PUBLIC "public"
+%token T_IMPORT "import"
+
+%nonassoc SHIFT_THERE
+%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY
+%nonassoc REDUCE_HERE
+
+%start UiProgram
+
+/.
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtDebug>
+
+#include <string.h>
+
+#include "javascriptengine_p.h"
+#include "javascriptlexer_p.h"
+#include "javascriptast_p.h"
+#include "javascriptnodepool_p.h"
+
+./
+
+/:
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// 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.
+//
+
+//
+// This file is automatically generated from javascript.g.
+// Changes will be lost.
+//
+
+#ifndef JAVASCRIPTPARSER_P_H
+#define JAVASCRIPTPARSER_P_H
+
+#include "javascriptgrammar_p.h"
+#include "javascriptast_p.h"
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class JavaScriptEnginePrivate;
+class JavaScriptNameIdImpl;
+
+class JavaScriptParser: protected $table
+{
+public:
+ union Value {
+ int ival;
+ double dval;
+ JavaScriptNameIdImpl *sval;
+ JavaScript::AST::ArgumentList *ArgumentList;
+ JavaScript::AST::CaseBlock *CaseBlock;
+ JavaScript::AST::CaseClause *CaseClause;
+ JavaScript::AST::CaseClauses *CaseClauses;
+ JavaScript::AST::Catch *Catch;
+ JavaScript::AST::DefaultClause *DefaultClause;
+ JavaScript::AST::ElementList *ElementList;
+ JavaScript::AST::Elision *Elision;
+ JavaScript::AST::ExpressionNode *Expression;
+ JavaScript::AST::Finally *Finally;
+ JavaScript::AST::FormalParameterList *FormalParameterList;
+ JavaScript::AST::FunctionBody *FunctionBody;
+ JavaScript::AST::FunctionDeclaration *FunctionDeclaration;
+ JavaScript::AST::Node *Node;
+ JavaScript::AST::PropertyName *PropertyName;
+ JavaScript::AST::PropertyNameAndValueList *PropertyNameAndValueList;
+ JavaScript::AST::SourceElement *SourceElement;
+ JavaScript::AST::SourceElements *SourceElements;
+ JavaScript::AST::Statement *Statement;
+ JavaScript::AST::StatementList *StatementList;
+ JavaScript::AST::Block *Block;
+ JavaScript::AST::VariableDeclaration *VariableDeclaration;
+ JavaScript::AST::VariableDeclarationList *VariableDeclarationList;
+
+ JavaScript::AST::UiProgram *UiProgram;
+ JavaScript::AST::UiImportList *UiImportList;
+ JavaScript::AST::UiImport *UiImport;
+ JavaScript::AST::UiPublicMember *UiPublicMember;
+ JavaScript::AST::UiObjectDefinition *UiObjectDefinition;
+ JavaScript::AST::UiObjectInitializer *UiObjectInitializer;
+ JavaScript::AST::UiObjectBinding *UiObjectBinding;
+ JavaScript::AST::UiScriptBinding *UiScriptBinding;
+ JavaScript::AST::UiArrayBinding *UiArrayBinding;
+ JavaScript::AST::UiObjectMember *UiObjectMember;
+ JavaScript::AST::UiObjectMemberList *UiObjectMemberList;
+ JavaScript::AST::UiQualifiedId *UiQualifiedId;
+ };
+
+ struct DiagnosticMessage {
+ enum Kind { Warning, Error };
+
+ DiagnosticMessage()
+ : kind(Error) {}
+
+ DiagnosticMessage(Kind kind, const JavaScript::AST::SourceLocation &loc, const QString &message)
+ : kind(kind), loc(loc), message(message) {}
+
+ bool isWarning() const
+ { return kind == Warning; }
+
+ bool isError() const
+ { return kind == Error; }
+
+ Kind kind;
+ JavaScript::AST::SourceLocation loc;
+ QString message;
+ };
+
+public:
+ JavaScriptParser();
+ ~JavaScriptParser();
+
+ bool parse(JavaScriptEnginePrivate *driver);
+
+ JavaScript::AST::UiProgram *ast()
+ { return program; }
+
+ QList<DiagnosticMessage> diagnosticMessages() const
+ { return diagnostic_messages; }
+
+ inline DiagnosticMessage diagnosticMessage() const
+ {
+ foreach (const DiagnosticMessage &d, diagnostic_messages) {
+ if (! d.kind == DiagnosticMessage::Warning)
+ return d;
+ }
+
+ return DiagnosticMessage();
+ }
+
+ inline QString errorMessage() const
+ { return diagnosticMessage().message; }
+
+ inline int errorLineNumber() const
+ { return diagnosticMessage().loc.startLine; }
+
+ inline int errorColumnNumber() const
+ { return diagnosticMessage().loc.startColumn; }
+
+protected:
+ void reallocateStack();
+
+ inline Value &sym(int index)
+ { return sym_stack [tos + index - 1]; }
+
+ inline JavaScript::AST::SourceLocation &loc(int index)
+ { return location_stack [tos + index - 1]; }
+
+protected:
+ int tos;
+ int stack_size;
+ Value *sym_stack;
+ int *state_stack;
+ JavaScript::AST::SourceLocation *location_stack;
+
+ JavaScript::AST::UiProgram *program;
+
+ // error recovery
+ enum { TOKEN_BUFFER_SIZE = 3 };
+
+ struct SavedToken {
+ int token;
+ double dval;
+ JavaScript::AST::SourceLocation loc;
+ };
+
+ double yylval;
+ JavaScript::AST::SourceLocation yylloc;
+ JavaScript::AST::SourceLocation yyprevlloc;
+
+ SavedToken token_buffer[TOKEN_BUFFER_SIZE];
+ SavedToken *first_token;
+ SavedToken *last_token;
+
+ QList<DiagnosticMessage> diagnostic_messages;
+};
+
+:/
+
+
+/.
+
+#include "javascriptparser_p.h"
+
+//
+// This file is automatically generated from javascript.g.
+// Changes will be lost.
+//
+
+using namespace JavaScript;
+
+QT_BEGIN_NAMESPACE
+
+void JavaScriptParser::reallocateStack()
+{
+ if (! stack_size)
+ stack_size = 128;
+ else
+ stack_size <<= 1;
+
+ sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
+ state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+ location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation)));
+}
+
+inline static bool automatic(JavaScriptEnginePrivate *driver, int token)
+{
+ return token == $table::T_RBRACE
+ || token == 0
+ || driver->lexer()->prevTerminator();
+}
+
+
+JavaScriptParser::JavaScriptParser():
+ tos(0),
+ stack_size(0),
+ sym_stack(0),
+ state_stack(0),
+ location_stack(0),
+ first_token(0),
+ last_token(0)
+{
+}
+
+JavaScriptParser::~JavaScriptParser()
+{
+ if (stack_size) {
+ qFree(sym_stack);
+ qFree(state_stack);
+ qFree(location_stack);
+ }
+}
+
+static inline AST::SourceLocation location(Lexer *lexer)
+{
+ AST::SourceLocation loc;
+ loc.offset = lexer->tokenOffset();
+ loc.length = lexer->tokenLength();
+ loc.startLine = lexer->startLineNo();
+ loc.startColumn = lexer->startColumnNo();
+ return loc;
+}
+
+bool JavaScriptParser::parse(JavaScriptEnginePrivate *driver)
+{
+ Lexer *lexer = driver->lexer();
+ bool hadErrors = false;
+ int yytoken = -1;
+ int action = 0;
+
+ first_token = last_token = 0;
+
+ tos = -1;
+ program = 0;
+
+ do {
+ if (++tos == stack_size)
+ reallocateStack();
+
+ state_stack[tos] = action;
+
+ _Lcheck_token:
+ if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
+ yyprevlloc = yylloc;
+
+ if (first_token == last_token) {
+ yytoken = lexer->lex();
+ yylval = lexer->dval();
+ yylloc = location(lexer);
+ } else {
+ yytoken = first_token->token;
+ yylval = first_token->dval;
+ yylloc = first_token->loc;
+ ++first_token;
+ }
+ }
+
+ action = t_action(action, yytoken);
+ if (action > 0) {
+ if (action != ACCEPT_STATE) {
+ yytoken = -1;
+ sym(1).dval = yylval;
+ loc(1) = yylloc;
+ } else {
+ --tos;
+ return ! hadErrors;
+ }
+ } else if (action < 0) {
+ const int r = -action - 1;
+ tos -= rhs[r];
+
+ switch (r) {
+./
+
+--------------------------------------------------------------------------------------------------------
+-- Declarative UI
+--------------------------------------------------------------------------------------------------------
+
+UiProgram: UiImportListOpt UiRootMember ;
+/.
+case $rule_number: {
+ program = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList,
+ sym(2).UiObjectMemberList->finish());
+ sym(1).UiProgram = program;
+} break;
+./
+
+UiImportListOpt: Empty ;
+UiImportListOpt: UiImportList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).UiImportList->finish();
+} break;
+./
+
+UiImportList: UiImport ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport);
+} break;
+./
+
+UiImportList: UiImportList UiImport ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(),
+ sym(1).UiImportList, sym(2).UiImport);
+} break;
+./
+
+UiImport: T_IMPORT T_STRING_LITERAL T_AUTOMATIC_SEMICOLON;
+UiImport: T_IMPORT T_STRING_LITERAL T_SEMICOLON;
+/.
+case $rule_number: {
+ AST::UiImport *node = makeAstNode<AST::UiImport>(driver->nodePool(), sym(2).sval);
+ node->importToken = loc(1);
+ node->fileNameToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+Empty: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+UiRootMember: UiObjectDefinition ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiObjectMemberList: UiObjectMember ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiObjectMemberList: UiObjectMemberList UiObjectMember ;
+/.
+case $rule_number: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(2).UiObjectMember);
+ sym(1).Node = node;
+} break;
+./
+
+UiArrayMemberList: UiObjectDefinition ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ;
+/.
+case $rule_number: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(3).UiObjectMember);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectInitializer: T_LBRACE T_RBRACE ;
+/.
+case $rule_number: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE ;
+/.
+case $rule_number: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish());
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: UiQualifiedId T_COLON T_IDENTIFIER UiObjectInitializer ;
+/.
+case $rule_number: {
+ AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(),
+ sym(3).sval, sym(4).UiObjectInitializer);
+ node->colonToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectDefinition: T_IDENTIFIER UiObjectInitializer ;
+/.
+case $rule_number: {
+ AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).sval,
+ sym(2).UiObjectInitializer);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: UiObjectDefinition ;
+
+UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(),
+ sym(4).UiObjectMemberList->finish());
+ node->colonToken = loc(2);
+ node->lbracketToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+UiMultilineStringLiteral: T_MULTILINE_STRING_LITERAL ;
+/.
+case $rule_number: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UiMultilineStringStatement: UiMultilineStringLiteral T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+UiMultilineStringStatement: UiMultilineStringLiteral T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: UiQualifiedId T_COLON UiMultilineStringStatement ;
+/. case $rule_number: ./
+UiObjectMember: UiQualifiedId T_COLON Statement ;
+/.
+case $rule_number: {
+ AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(),
+ sym(3).Statement);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiPropertyType: T_VAR ;
+/.
+case $rule_number:
+./
+UiPropertyType: T_RESERVED_WORD ;
+/.
+case $rule_number: {
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+ break;
+}
+./
+
+UiPropertyType: T_IDENTIFIER ;
+
+UiObjectMember: T_SIGNAL T_IDENTIFIER ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (JavaScriptNameIdImpl *)0, sym(2).sval);
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->semicolonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->semicolonToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval,
+ sym(5).Expression);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->colonToken = loc(4);
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: FunctionDeclaration ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+./
+
+UiObjectMember: VariableStatement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+./
+
+UiQualifiedId: T_RESERVED_WORD ;
+/.case $rule_number: ./
+
+UiQualifiedId: T_RETURN ;
+/.
+case $rule_number:
+{
+ AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+JsIdentifier: T_IDENTIFIER;
+
+JsIdentifier: T_PROPERTY ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(JavaScriptGrammar::spell[T_PROPERTY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+./
+
+JsIdentifier: T_SIGNAL ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(JavaScriptGrammar::spell[T_SIGNAL]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+./
+
+UiQualifiedId: JsIdentifier ;
+/.
+case $rule_number: {
+ AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UiQualifiedId: UiQualifiedId T_DOT JsIdentifier ;
+/.
+case $rule_number: {
+ AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+
+--------------------------------------------------------------------------------------------------------
+-- Expressions
+--------------------------------------------------------------------------------------------------------
+
+PrimaryExpression: T_THIS ;
+/.
+case $rule_number: {
+ AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool());
+ node->thisToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: JsIdentifier ;
+/.
+case $rule_number: {
+ AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_NULL ;
+/.
+case $rule_number: {
+ AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool());
+ node->nullToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_TRUE ;
+/.
+case $rule_number: {
+ AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool());
+ node->trueToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_FALSE ;
+/.
+case $rule_number: {
+ AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool());
+ node->falseToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_NUMERIC_LITERAL ;
+/.
+case $rule_number: {
+ AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_STRING_LITERAL ;
+/.
+case $rule_number: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_DIVIDE_ ;
+/:
+#define J_SCRIPT_REGEXPLITERAL_RULE1 $rule_number
+:/
+/.
+case $rule_number: {
+ bool rx = lexer->scanRegExp(Lexer::NoPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false; // ### remove me
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_DIVIDE_EQ ;
+/:
+#define J_SCRIPT_REGEXPLITERAL_RULE2 $rule_number
+:/
+/.
+case $rule_number: {
+ bool rx = lexer->scanRegExp(Lexer::EqualPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false;
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElisionOpt T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision);
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElementList T_COMMA ElisionOpt T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), sym(4).Elision);
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+-- PrimaryExpression: T_LBRACE T_RBRACE ;
+-- /.
+-- case $rule_number: {
+-- sym(1).Node = makeAstNode<AST::ObjectLiteral> (driver->nodePool());
+-- } break;
+-- ./
+
+PrimaryExpression: T_LBRACE PropertyNameAndValueListOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::ObjectLiteral *node = 0;
+ if (sym(2).Node)
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ else
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACE PropertyNameAndValueList T_COMMA T_RBRACE ;
+/.
+case $rule_number: {
+ AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LPAREN Expression T_RPAREN ;
+/.
+case $rule_number: {
+ AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression);
+ node->lparenToken = loc(1);
+ node->rparenToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+ElementList: ElisionOpt AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision, sym(2).Expression);
+} break;
+./
+
+ElementList: ElementList T_COMMA ElisionOpt AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision, sym(4).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+Elision: T_COMMA ;
+/.
+case $rule_number: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool());
+ node->commaToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+Elision: Elision T_COMMA ;
+/.
+case $rule_number: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ElisionOpt: %prec SHIFT_THERE ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ElisionOpt: Elision ;
+/.
+case $rule_number: {
+ sym(1).Elision = sym(1).Elision->finish ();
+} break;
+./
+
+PropertyNameAndValueList: PropertyName T_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyName, sym(3).Expression);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyNameAndValueList: PropertyNameAndValueList T_COMMA PropertyName T_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression);
+ node->commaToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_IDENTIFIER %prec REDUCE_HERE ;
+/.
+case $rule_number: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_SIGNAL ;
+/.case $rule_number:./
+
+PropertyName: T_PROPERTY ;
+/.
+case $rule_number: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_STRING_LITERAL ;
+/.
+case $rule_number: {
+ AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_NUMERIC_LITERAL ;
+/.
+case $rule_number: {
+ AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: ReservedIdentifier ;
+/.
+case $rule_number: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+ReservedIdentifier: T_BREAK ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CASE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CATCH ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CONTINUE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DEFAULT ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DELETE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DO ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_ELSE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FALSE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FINALLY ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FOR ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FUNCTION ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_IF ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_IN ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_INSTANCEOF ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_NEW ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_NULL ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_RETURN ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_SWITCH ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_THIS ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_THROW ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_TRUE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_TRY ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_TYPEOF ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_VAR ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_VOID ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_WHILE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CONST ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DEBUGGER ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_RESERVED_WORD ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_WITH ;
+/.
+case $rule_number:
+{
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+} break;
+./
+
+PropertyIdentifier: JsIdentifier ;
+PropertyIdentifier: ReservedIdentifier ;
+
+MemberExpression: PrimaryExpression ;
+MemberExpression: FunctionExpression ;
+
+MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+MemberExpression: MemberExpression T_DOT PropertyIdentifier ;
+/.
+case $rule_number: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+MemberExpression: T_NEW MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+/.
+case $rule_number: {
+ AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList);
+ node->newToken = loc(1);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+NewExpression: MemberExpression ;
+
+NewExpression: T_NEW NewExpression ;
+/.
+case $rule_number: {
+ AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression);
+ node->newToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+/.
+case $rule_number: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: CallExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+/.
+case $rule_number: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: CallExpression T_DOT PropertyIdentifier ;
+/.
+case $rule_number: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+ArgumentListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ArgumentListOpt: ArgumentList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).ArgumentList->finish();
+} break;
+./
+
+ArgumentList: AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression);
+} break;
+./
+
+ArgumentList: ArgumentList T_COMMA AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LeftHandSideExpression: NewExpression ;
+LeftHandSideExpression: CallExpression ;
+PostfixExpression: LeftHandSideExpression ;
+
+PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ;
+/.
+case $rule_number: {
+ AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->incrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ;
+/.
+case $rule_number: {
+ AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->decrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: PostfixExpression ;
+
+UnaryExpression: T_DELETE UnaryExpression ;
+/.
+case $rule_number: {
+ AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression);
+ node->deleteToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_VOID UnaryExpression ;
+/.
+case $rule_number: {
+ AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression);
+ node->voidToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_TYPEOF UnaryExpression ;
+/.
+case $rule_number: {
+ AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression);
+ node->typeofToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_PLUS_PLUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->incrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_MINUS_MINUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->decrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_PLUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression);
+ node->plusToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_MINUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression);
+ node->minusToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_TILDE UnaryExpression ;
+/.
+case $rule_number: {
+ AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression);
+ node->tildeToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_NOT UnaryExpression ;
+/.
+case $rule_number: {
+ AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression);
+ node->notToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+MultiplicativeExpression: UnaryExpression ;
+
+MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mul, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Div, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mod, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AdditiveExpression: MultiplicativeExpression ;
+
+AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Add, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Sub, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ShiftExpression: AdditiveExpression ;
+
+ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::LShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::RShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::URShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: ShiftExpression ;
+
+RelationalExpression: RelationalExpression T_LT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_GT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_LE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_GE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_IN ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::In, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: ShiftExpression ;
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: RelationalExpression ;
+
+EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: RelationalExpressionNotIn ;
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseANDExpression: EqualityExpression ;
+
+BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseANDExpressionNotIn: EqualityExpressionNotIn ;
+
+BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseXORExpression: BitwiseANDExpression ;
+
+BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ;
+
+BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseORExpression: BitwiseXORExpression ;
+
+BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ;
+
+BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalANDExpression: BitwiseORExpression ;
+
+LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ;
+
+LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalORExpression: LogicalANDExpression ;
+
+LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalORExpressionNotIn: LogicalANDExpressionNotIn ;
+
+LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ConditionalExpression: LogicalORExpression ;
+
+ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+ConditionalExpressionNotIn: LogicalORExpressionNotIn ;
+
+ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+AssignmentExpression: ConditionalExpression ;
+
+AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AssignmentExpressionNotIn: ConditionalExpressionNotIn ;
+
+AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AssignmentOperator: T_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::Assign;
+} break;
+./
+
+AssignmentOperator: T_STAR_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceMul;
+} break;
+./
+
+AssignmentOperator: T_DIVIDE_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceDiv;
+} break;
+./
+
+AssignmentOperator: T_REMAINDER_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceMod;
+} break;
+./
+
+AssignmentOperator: T_PLUS_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceAdd;
+} break;
+./
+
+AssignmentOperator: T_MINUS_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceSub;
+} break;
+./
+
+AssignmentOperator: T_LT_LT_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceLeftShift;
+} break;
+./
+
+AssignmentOperator: T_GT_GT_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceRightShift;
+} break;
+./
+
+AssignmentOperator: T_GT_GT_GT_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceURightShift;
+} break;
+./
+
+AssignmentOperator: T_AND_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceAnd;
+} break;
+./
+
+AssignmentOperator: T_XOR_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceXor;
+} break;
+./
+
+AssignmentOperator: T_OR_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceOr;
+} break;
+./
+
+Expression: AssignmentExpression ;
+
+Expression: Expression T_COMMA AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ExpressionOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ExpressionOpt: Expression ;
+
+ExpressionNotIn: AssignmentExpressionNotIn ;
+
+ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ExpressionNotInOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ExpressionNotInOpt: ExpressionNotIn ;
+
+Statement: Block ;
+Statement: VariableStatement ;
+Statement: EmptyStatement ;
+Statement: ExpressionStatement ;
+Statement: IfStatement ;
+Statement: IterationStatement ;
+Statement: ContinueStatement ;
+Statement: BreakStatement ;
+Statement: ReturnStatement ;
+Statement: WithStatement ;
+Statement: LabelledStatement ;
+Statement: SwitchStatement ;
+Statement: ThrowStatement ;
+Statement: TryStatement ;
+Statement: DebuggerStatement ;
+
+
+Block: T_LBRACE StatementListOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+StatementList: Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement);
+} break;
+./
+
+StatementList: StatementList Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement);
+} break;
+./
+
+StatementListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+StatementListOpt: StatementList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).StatementList->finish ();
+} break;
+./
+
+VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(),
+ sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST));
+ node->declarationKindToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+VariableDeclarationKind: T_CONST ;
+/.
+case $rule_number: {
+ sym(1).ival = T_CONST;
+} break;
+./
+
+VariableDeclarationKind: T_VAR ;
+/.
+case $rule_number: {
+ sym(1).ival = T_VAR;
+} break;
+./
+
+VariableDeclarationList: VariableDeclaration ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+./
+
+VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ;
+/.
+case $rule_number: {
+ AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(),
+ sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+VariableDeclarationListNotIn: VariableDeclarationNotIn ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+./
+
+VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+} break;
+./
+
+VariableDeclaration: JsIdentifier InitialiserOpt ;
+/.
+case $rule_number: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ;
+/.
+case $rule_number: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+Initialiser: T_EQ AssignmentExpression ;
+/.
+case $rule_number: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+./
+
+InitialiserOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+InitialiserOpt: Initialiser ;
+
+InitialiserNotIn: T_EQ AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+./
+
+InitialiserNotInOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+InitialiserNotInOpt: InitialiserNotIn ;
+
+EmptyStatement: T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool());
+ node->semicolonToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ExpressionStatement: Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ;
+/.
+case $rule_number: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->elseToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression);
+ node->doToken = loc(1);
+ node->whileToken = loc(3);
+ node->lparenToken = loc(4);
+ node->rparenToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->whileToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Expression, sym(9).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->firstSemicolonToken = loc(4);
+ node->secondSemicolonToken = loc(6);
+ node->rparenToken = loc(8);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(),
+ sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression,
+ sym(8).Expression, sym(10).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->firstSemicolonToken = loc(5);
+ node->secondSemicolonToken = loc(7);
+ node->rparenToken = loc(9);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->inToken = loc(4);
+ node->rparenToken = loc(6);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(),
+ sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->inToken = loc(5);
+ node->rparenToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ContinueStatement: T_CONTINUE T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool());
+ node->continueToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ContinueStatement: T_CONTINUE JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ContinueStatement: T_CONTINUE JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval);
+ node->continueToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+BreakStatement: T_BREAK T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool());
+ node->breakToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BreakStatement: T_BREAK JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+BreakStatement: T_BREAK JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval);
+ node->breakToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression);
+ node->returnToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->withToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ;
+/.
+case $rule_number: {
+ AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock);
+ node->switchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+CaseClauses: CaseClause ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause);
+} break;
+./
+
+CaseClauses: CaseClauses CaseClause ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause);
+} break;
+./
+
+CaseClausesOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+CaseClausesOpt: CaseClauses ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).CaseClauses->finish ();
+} break;
+./
+
+CaseClause: T_CASE Expression T_COLON StatementListOpt ;
+/.
+case $rule_number: {
+ AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList);
+ node->caseToken = loc(1);
+ node->colonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+DefaultClause: T_DEFAULT T_COLON StatementListOpt ;
+/.
+case $rule_number: {
+ AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList);
+ node->defaultToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LabelledStatement: T_SIGNAL T_COLON Statement ;
+/.case $rule_number:./
+
+LabelledStatement: T_PROPERTY T_COLON Statement ;
+/.
+case $rule_number: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LabelledStatement: T_IDENTIFIER T_COLON Statement ;
+/.
+case $rule_number: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ThrowStatement: T_THROW Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression);
+ node->throwToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+TryStatement: T_TRY Block Catch ;
+/.
+case $rule_number: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+TryStatement: T_TRY Block Finally ;
+/.
+case $rule_number: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+TryStatement: T_TRY Block Catch Finally ;
+/.
+case $rule_number: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+Catch: T_CATCH T_LPAREN JsIdentifier T_RPAREN Block ;
+/.
+case $rule_number: {
+ AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block);
+ node->catchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->identifierToken = loc(3);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+Finally: T_FINALLY Block ;
+/.
+case $rule_number: {
+ AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block);
+ node->finallyToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+DebuggerStatement: T_DEBUGGER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool());
+ node->debuggerToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+FunctionDeclaration: T_FUNCTION JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+./
+
+FunctionExpression: T_FUNCTION IdentifierOpt T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ if (sym(2).sval)
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+./
+
+FormalParameterList: JsIdentifier ;
+/.
+case $rule_number: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+FormalParameterList: FormalParameterList T_COMMA JsIdentifier ;
+/.
+case $rule_number: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+FormalParameterListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+FormalParameterListOpt: FormalParameterList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).FormalParameterList->finish ();
+} break;
+./
+
+FunctionBodyOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+FunctionBodyOpt: FunctionBody ;
+
+FunctionBody: SourceElements ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ());
+} break;
+./
+
+--JavaScriptProgram: SourceElements ;
+--/.
+--case $rule_number: {
+-- sym(1).Node = makeAstNode<AST::Program> (driver->nodePool(), sym(1).SourceElements->finish ());
+-- driver->changeAbstractSyntaxTree(sym(1).Node);
+--} break;
+--./
+
+SourceElements: SourceElement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement);
+} break;
+./
+
+SourceElements: SourceElements SourceElement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement);
+} break;
+./
+
+SourceElement: Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement);
+} break;
+./
+
+SourceElement: FunctionDeclaration ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration);
+} break;
+./
+
+IdentifierOpt: ;
+/.
+case $rule_number: {
+ sym(1).sval = 0;
+} break;
+./
+
+IdentifierOpt: JsIdentifier ;
+
+PropertyNameAndValueListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+PropertyNameAndValueListOpt: PropertyNameAndValueList ;
+
+/.
+ } // switch
+ action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT);
+ } // if
+ } while (action != 0);
+
+ if (first_token == last_token) {
+ const int errorState = state_stack[tos];
+
+ // automatic insertion of `;'
+ if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) {
+ SavedToken &tk = token_buffer[0];
+ tk.token = yytoken;
+ tk.dval = yylval;
+ tk.loc = yylloc;
+
+ yylloc = yyprevlloc;
+ yylloc.offset += yylloc.length;
+ yylloc.startColumn += yylloc.length;
+ yylloc.length = 0;
+
+ //const QString msg = QString::fromUtf8("Missing `;'");
+ //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg));
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ yytoken = T_SEMICOLON;
+ yylval = 0;
+
+ action = errorState;
+
+ goto _Lcheck_token;
+ }
+
+ hadErrors = true;
+
+ token_buffer[0].token = yytoken;
+ token_buffer[0].dval = yylval;
+ token_buffer[0].loc = yylloc;
+
+ token_buffer[1].token = yytoken = lexer->lex();
+ token_buffer[1].dval = yylval = lexer->dval();
+ token_buffer[1].loc = yylloc = location(lexer);
+
+ if (t_action(errorState, yytoken)) {
+ const QString msg = QString::fromUtf8("Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+
+ static int tokens[] = {
+ T_PLUS,
+ T_EQ,
+
+ T_COMMA,
+ T_COLON,
+ T_SEMICOLON,
+
+ T_RPAREN, T_RBRACKET, T_RBRACE,
+
+ T_NUMERIC_LITERAL,
+ T_IDENTIFIER,
+
+ T_LPAREN, T_LBRACKET, T_LBRACE,
+
+ EOF_SYMBOL
+ };
+
+ for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
+ int a = t_action(errorState, *tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[*tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = *tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[2];
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ for (int tk = 1; tk < TERMINAL_COUNT; ++tk) {
+ if (tk == T_AUTOMATIC_SEMICOLON)
+ continue;
+
+ int a = t_action(errorState, tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ const QString msg = QString::fromUtf8("Syntax error");
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
+
+
+./
+/:
+QT_END_NAMESPACE
+
+
+
+#endif // JAVASCRIPTPARSER_P_H
+:/
diff --git a/src/declarative/qml/parser/javascriptast.cpp b/src/declarative/qml/parser/javascriptast.cpp
new file mode 100644
index 0000000..8a10650
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptast.cpp
@@ -0,0 +1,912 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "javascriptast_p.h"
+
+
+
+#include "javascriptastvisitor_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript { namespace AST {
+
+ExpressionNode *Node::expressionCast()
+{
+ return 0;
+}
+
+BinaryExpression *Node::binaryExpressionCast()
+{
+ return 0;
+}
+
+Statement *Node::statementCast()
+{
+ return 0;
+}
+
+ExpressionNode *ExpressionNode::expressionCast()
+{
+ return this;
+}
+
+BinaryExpression *BinaryExpression::binaryExpressionCast()
+{
+ return this;
+}
+
+Statement *Statement::statementCast()
+{
+ return this;
+}
+
+void NestedExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void ThisExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void IdentifierExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void NullExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void TrueLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void FalseLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void StringLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void NumericLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void RegExpLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArrayLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(elements, visitor);
+ acceptChild(elision, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ObjectLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(properties, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ElementList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ ElementList *it = this;
+ do {
+ acceptChild(it->elision, visitor);
+ acceptChild(it->expression, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Elision::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ // ###
+ }
+
+ visitor->endVisit(this);
+}
+
+void PropertyNameAndValueList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ PropertyNameAndValueList *it = this;
+ do {
+ acceptChild(it->name, visitor);
+ acceptChild(it->value, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void IdentifierPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void StringLiteralPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void NumericLiteralPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArrayMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(base, visitor);
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FieldMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NewMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(base, visitor);
+ acceptChild(arguments, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NewExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CallExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(base, visitor);
+ acceptChild(arguments, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArgumentList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ ArgumentList *it = this;
+ do {
+ acceptChild(it->expression, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PostIncrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PostDecrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DeleteExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VoidExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TypeOfExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PreIncrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PreDecrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UnaryPlusExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UnaryMinusExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TildeExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NotExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void BinaryExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(left, visitor);
+ acceptChild(right, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ConditionalExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ acceptChild(ok, visitor);
+ acceptChild(ko, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Expression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(left, visitor);
+ acceptChild(right, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Block::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void StatementList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ StatementList *it = this;
+ do {
+ acceptChild(it->statement, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(declarations, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableDeclarationList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ VariableDeclarationList *it = this;
+ do {
+ acceptChild(it->declaration, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableDeclaration::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void EmptyStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ExpressionStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void IfStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ acceptChild(ok, visitor);
+ acceptChild(ko, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DoWhileStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statement, visitor);
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void WhileStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ForStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(initialiser, visitor);
+ acceptChild(condition, visitor);
+ acceptChild(expression, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LocalForStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(declarations, visitor);
+ acceptChild(condition, visitor);
+ acceptChild(expression, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ForEachStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(initialiser, visitor);
+ acceptChild(expression, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LocalForEachStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(declaration, visitor);
+ acceptChild(expression, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ContinueStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void BreakStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ReturnStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void WithStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void SwitchStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ acceptChild(block, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseBlock::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(clauses, visitor);
+ acceptChild(defaultClause, visitor);
+ acceptChild(moreClauses, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseClauses::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ CaseClauses *it = this;
+ do {
+ acceptChild(it->clause, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseClause::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ acceptChild(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DefaultClause::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LabelledStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ThrowStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TryStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statement, visitor);
+ acceptChild(catchExpression, visitor);
+ acceptChild(finallyExpression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Catch::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Finally::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionDeclaration::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(formals, visitor);
+ acceptChild(body, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(formals, visitor);
+ acceptChild(body, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FormalParameterList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ // ###
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionBody::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(elements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Program::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(elements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void SourceElements::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ SourceElements *it = this;
+ do {
+ acceptChild(it->element, visitor);
+ it = it->next;
+ } while (it);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(declaration, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void StatementSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DebuggerStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+
+void UiProgram::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiObjectMemberList *it = members; it; it = it->next)
+ acceptChild(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiPublicMember::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectDefinition::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(initializer, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectInitializer::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiObjectMemberList *it = members; it; it = it->next)
+ acceptChild(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(qualifiedId, visitor);
+ acceptChild(initializer, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiScriptBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(qualifiedId, visitor);
+ acceptChild(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiArrayBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(qualifiedId, visitor);
+ for (UiObjectMemberList *it = members; it; it = it->next)
+ acceptChild(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectMemberList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiObjectMemberList *it = this; it; it = it->next)
+ acceptChild(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiQualifiedId::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiImport::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiImportList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(import, visitor);
+ acceptChild(next, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ acceptChild(sourceElement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+} } // namespace JavaScript::AST
+
+QT_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/javascriptast_p.h b/src/declarative/qml/parser/javascriptast_p.h
new file mode 100644
index 0000000..cd47e42
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptast_p.h
@@ -0,0 +1,2519 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTAST_P_H
+#define JAVASCRIPTAST_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QString>
+
+
+
+#include "javascriptastvisitor_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#define JAVASCRIPT_DECLARE_AST_NODE(name) \
+ enum { K = Kind_##name };
+
+class JavaScriptNameIdImpl;
+
+namespace QSOperator // ### rename
+{
+
+enum Op {
+ Add,
+ And,
+ InplaceAnd,
+ Assign,
+ BitAnd,
+ BitOr,
+ BitXor,
+ InplaceSub,
+ Div,
+ InplaceDiv,
+ Equal,
+ Ge,
+ Gt,
+ In,
+ InplaceAdd,
+ InstanceOf,
+ Le,
+ LShift,
+ InplaceLeftShift,
+ Lt,
+ Mod,
+ InplaceMod,
+ Mul,
+ InplaceMul,
+ NotEqual,
+ Or,
+ InplaceOr,
+ RShift,
+ InplaceRightShift,
+ StrictEqual,
+ StrictNotEqual,
+ Sub,
+ URShift,
+ InplaceURightShift,
+ InplaceXor
+};
+
+} // namespace QSOperator
+
+namespace JavaScript { namespace AST {
+
+template <typename _T1, typename _T2>
+_T1 cast(_T2 *ast)
+{
+ if (ast && ast->kind == static_cast<_T1>(0)->K)
+ return static_cast<_T1>(ast);
+
+ return 0;
+}
+
+class SourceLocation
+{
+public:
+ SourceLocation(quint32 offset = 0, quint32 length = 0)
+ : offset(offset), length(length),
+ startLine(0), startColumn(0)
+ { }
+
+ bool isValid() const { return length != 0; }
+
+ quint32 begin() const { return offset; }
+ quint32 end() const { return offset + length; }
+
+// attributes
+ // ### encode
+ quint32 offset;
+ quint32 length;
+ quint32 startLine;
+ quint32 startColumn;
+};
+
+class Node
+{
+public:
+ enum Kind {
+ Kind_Undefined,
+
+ Kind_ArgumentList,
+ Kind_ArrayLiteral,
+ Kind_ArrayMemberExpression,
+ Kind_BinaryExpression,
+ Kind_Block,
+ Kind_BreakStatement,
+ Kind_CallExpression,
+ Kind_CaseBlock,
+ Kind_CaseClause,
+ Kind_CaseClauses,
+ Kind_Catch,
+ Kind_ConditionalExpression,
+ Kind_ContinueStatement,
+ Kind_DebuggerStatement,
+ Kind_DefaultClause,
+ Kind_DeleteExpression,
+ Kind_DoWhileStatement,
+ Kind_ElementList,
+ Kind_Elision,
+ Kind_EmptyStatement,
+ Kind_Expression,
+ Kind_ExpressionStatement,
+ Kind_FalseLiteral,
+ Kind_FieldMemberExpression,
+ Kind_Finally,
+ Kind_ForEachStatement,
+ Kind_ForStatement,
+ Kind_FormalParameterList,
+ Kind_FunctionBody,
+ Kind_FunctionDeclaration,
+ Kind_FunctionExpression,
+ Kind_FunctionSourceElement,
+ Kind_IdentifierExpression,
+ Kind_IdentifierPropertyName,
+ Kind_IfStatement,
+ Kind_LabelledStatement,
+ Kind_LocalForEachStatement,
+ Kind_LocalForStatement,
+ Kind_NewExpression,
+ Kind_NewMemberExpression,
+ Kind_NotExpression,
+ Kind_NullExpression,
+ Kind_NumericLiteral,
+ Kind_NumericLiteralPropertyName,
+ Kind_ObjectLiteral,
+ Kind_PostDecrementExpression,
+ Kind_PostIncrementExpression,
+ Kind_PreDecrementExpression,
+ Kind_PreIncrementExpression,
+ Kind_Program,
+ Kind_PropertyName,
+ Kind_PropertyNameAndValueList,
+ Kind_RegExpLiteral,
+ Kind_ReturnStatement,
+ Kind_SourceElement,
+ Kind_SourceElements,
+ Kind_StatementList,
+ Kind_StatementSourceElement,
+ Kind_StringLiteral,
+ Kind_StringLiteralPropertyName,
+ Kind_SwitchStatement,
+ Kind_ThisExpression,
+ Kind_ThrowStatement,
+ Kind_TildeExpression,
+ Kind_TrueLiteral,
+ Kind_TryStatement,
+ Kind_TypeOfExpression,
+ Kind_UnaryMinusExpression,
+ Kind_UnaryPlusExpression,
+ Kind_VariableDeclaration,
+ Kind_VariableDeclarationList,
+ Kind_VariableStatement,
+ Kind_VoidExpression,
+ Kind_WhileStatement,
+ Kind_WithStatement,
+ Kind_NestedExpression,
+
+ Kind_UiArrayBinding,
+ Kind_UiImport,
+ Kind_UiImportList,
+ Kind_UiObjectBinding,
+ Kind_UiObjectDefinition,
+ Kind_UiObjectInitializer,
+ Kind_UiObjectMemberList,
+ Kind_UiProgram,
+ Kind_UiPublicMember,
+ Kind_UiQualifiedId,
+ Kind_UiScriptBinding,
+ Kind_UiSourceElement
+ };
+
+ inline Node()
+ : kind(Kind_Undefined) {}
+
+ virtual ~Node() {}
+
+ virtual ExpressionNode *expressionCast();
+ virtual BinaryExpression *binaryExpressionCast();
+ virtual Statement *statementCast();
+
+ inline void accept(Visitor *visitor)
+ {
+ if (visitor->preVisit(this)) {
+ accept0(visitor);
+ visitor->postVisit(this);
+ }
+ }
+
+ static void acceptChild(Node *node, Visitor *visitor)
+ {
+ if (node)
+ node->accept(visitor);
+ }
+
+ virtual void accept0(Visitor *visitor) = 0;
+
+// attributes
+ int kind;
+};
+
+class ExpressionNode: public Node
+{
+public:
+ ExpressionNode() {}
+ virtual ~ExpressionNode() {}
+
+ virtual ExpressionNode *expressionCast();
+
+ virtual SourceLocation firstSourceLocation() const = 0;
+ virtual SourceLocation lastSourceLocation() const = 0;
+};
+
+class Statement: public Node
+{
+public:
+ Statement() {}
+ virtual ~Statement() {}
+
+ virtual Statement *statementCast();
+
+ virtual SourceLocation firstSourceLocation() const = 0;
+ virtual SourceLocation lastSourceLocation() const = 0;
+};
+
+class NestedExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NestedExpression)
+
+ NestedExpression(ExpressionNode *expression)
+ : expression(expression)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lparenToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rparenToken; }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class ThisExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ThisExpression)
+
+ ThisExpression() { kind = K; }
+ virtual ~ThisExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return thisToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return thisToken; }
+
+// attributes
+ SourceLocation thisToken;
+};
+
+class IdentifierExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(IdentifierExpression)
+
+ IdentifierExpression(JavaScriptNameIdImpl *n):
+ name (n) { kind = K; }
+
+ virtual ~IdentifierExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return identifierToken; }
+
+// attributes
+ JavaScriptNameIdImpl *name;
+ SourceLocation identifierToken;
+};
+
+class NullExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NullExpression)
+
+ NullExpression() { kind = K; }
+ virtual ~NullExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return nullToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return nullToken; }
+
+// attributes
+ SourceLocation nullToken;
+};
+
+class TrueLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(TrueLiteral)
+
+ TrueLiteral() { kind = K; }
+ virtual ~TrueLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return trueToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return trueToken; }
+
+// attributes
+ SourceLocation trueToken;
+};
+
+class FalseLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FalseLiteral)
+
+ FalseLiteral() { kind = K; }
+ virtual ~FalseLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return falseToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return falseToken; }
+
+// attributes
+ SourceLocation falseToken;
+};
+
+class NumericLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NumericLiteral)
+
+ NumericLiteral(double v):
+ value (v) { kind = K; }
+ virtual ~NumericLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ double value;
+ SourceLocation literalToken;
+};
+
+class StringLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(StringLiteral)
+
+ StringLiteral(JavaScriptNameIdImpl *v):
+ value (v) { kind = K; }
+
+ virtual ~StringLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ JavaScriptNameIdImpl *value;
+ SourceLocation literalToken;
+};
+
+class RegExpLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(RegExpLiteral)
+
+ RegExpLiteral(JavaScriptNameIdImpl *p, int f):
+ pattern (p), flags (f) { kind = K; }
+
+ virtual ~RegExpLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ JavaScriptNameIdImpl *pattern;
+ int flags;
+ SourceLocation literalToken;
+};
+
+class ArrayLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ArrayLiteral)
+
+ ArrayLiteral(Elision *e):
+ elements (0), elision (e)
+ { kind = K; }
+
+ ArrayLiteral(ElementList *elts):
+ elements (elts), elision (0)
+ { kind = K; }
+
+ ArrayLiteral(ElementList *elts, Elision *e):
+ elements (elts), elision (e)
+ { kind = K; }
+
+ virtual ~ArrayLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbracketToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+// attributes
+ ElementList *elements;
+ Elision *elision;
+ SourceLocation lbracketToken;
+ SourceLocation commaToken;
+ SourceLocation rbracketToken;
+};
+
+class ObjectLiteral: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ObjectLiteral)
+
+ ObjectLiteral():
+ properties (0) { kind = K; }
+
+ ObjectLiteral(PropertyNameAndValueList *plist):
+ properties (plist) { kind = K; }
+
+ virtual ~ObjectLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbraceToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbraceToken; }
+
+// attributes
+ PropertyNameAndValueList *properties;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class ElementList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ElementList)
+
+ ElementList(Elision *e, ExpressionNode *expr):
+ elision (e), expression (expr), next (this)
+ { kind = K; }
+
+ ElementList(ElementList *previous, Elision *e, ExpressionNode *expr):
+ elision (e), expression (expr)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~ElementList() {}
+
+ inline ElementList *finish ()
+ {
+ ElementList *front = next;
+ next = 0;
+ return front;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Elision *elision;
+ ExpressionNode *expression;
+ ElementList *next;
+ SourceLocation commaToken;
+};
+
+class Elision: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(Elision)
+
+ Elision():
+ next (this) { kind = K; }
+
+ Elision(Elision *previous)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~Elision() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline Elision *finish ()
+ {
+ Elision *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ Elision *next;
+ SourceLocation commaToken;
+};
+
+class PropertyNameAndValueList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(PropertyNameAndValueList)
+
+ PropertyNameAndValueList(PropertyName *n, ExpressionNode *v):
+ name (n), value (v), next (this)
+ { kind = K; }
+
+ PropertyNameAndValueList(PropertyNameAndValueList *previous, PropertyName *n, ExpressionNode *v):
+ name (n), value (v)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~PropertyNameAndValueList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline PropertyNameAndValueList *finish ()
+ {
+ PropertyNameAndValueList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ PropertyName *name;
+ ExpressionNode *value;
+ PropertyNameAndValueList *next;
+ SourceLocation colonToken;
+ SourceLocation commaToken;
+};
+
+class PropertyName: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(PropertyName)
+
+ PropertyName() { kind = K; }
+ virtual ~PropertyName() {}
+
+// attributes
+ SourceLocation propertyNameToken;
+};
+
+class IdentifierPropertyName: public PropertyName
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(IdentifierPropertyName)
+
+ IdentifierPropertyName(JavaScriptNameIdImpl *n):
+ id (n) { kind = K; }
+
+ virtual ~IdentifierPropertyName() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ JavaScriptNameIdImpl *id;
+};
+
+class StringLiteralPropertyName: public PropertyName
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(StringLiteralPropertyName)
+
+ StringLiteralPropertyName(JavaScriptNameIdImpl *n):
+ id (n) { kind = K; }
+ virtual ~StringLiteralPropertyName() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ JavaScriptNameIdImpl *id;
+};
+
+class NumericLiteralPropertyName: public PropertyName
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NumericLiteralPropertyName)
+
+ NumericLiteralPropertyName(double n):
+ id (n) { kind = K; }
+ virtual ~NumericLiteralPropertyName() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ double id;
+};
+
+class ArrayMemberExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ArrayMemberExpression)
+
+ ArrayMemberExpression(ExpressionNode *b, ExpressionNode *e):
+ base (b), expression (e)
+ { kind = K; }
+
+ virtual ~ArrayMemberExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+// attributes
+ ExpressionNode *base;
+ ExpressionNode *expression;
+ SourceLocation lbracketToken;
+ SourceLocation rbracketToken;
+};
+
+class FieldMemberExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FieldMemberExpression)
+
+ FieldMemberExpression(ExpressionNode *b, JavaScriptNameIdImpl *n):
+ base (b), name (n)
+ { kind = K; }
+
+ virtual ~FieldMemberExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return identifierToken; }
+
+ // attributes
+ ExpressionNode *base;
+ JavaScriptNameIdImpl *name;
+ SourceLocation dotToken;
+ SourceLocation identifierToken;
+};
+
+class NewMemberExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NewMemberExpression)
+
+ NewMemberExpression(ExpressionNode *b, ArgumentList *a):
+ base (b), arguments (a)
+ { kind = K; }
+
+ virtual ~NewMemberExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return newToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rparenToken; }
+
+ // attributes
+ ExpressionNode *base;
+ ArgumentList *arguments;
+ SourceLocation newToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class NewExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NewExpression)
+
+ NewExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~NewExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return newToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation newToken;
+};
+
+class CallExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(CallExpression)
+
+ CallExpression(ExpressionNode *b, ArgumentList *a):
+ base (b), arguments (a)
+ { kind = K; }
+
+ virtual ~CallExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rparenToken; }
+
+// attributes
+ ExpressionNode *base;
+ ArgumentList *arguments;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class ArgumentList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ArgumentList)
+
+ ArgumentList(ExpressionNode *e):
+ expression (e), next (this)
+ { kind = K; }
+
+ ArgumentList(ArgumentList *previous, ExpressionNode *e):
+ expression (e)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~ArgumentList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline ArgumentList *finish ()
+ {
+ ArgumentList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ ExpressionNode *expression;
+ ArgumentList *next;
+ SourceLocation commaToken;
+};
+
+class PostIncrementExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(PostIncrementExpression)
+
+ PostIncrementExpression(ExpressionNode *b):
+ base (b) { kind = K; }
+
+ virtual ~PostIncrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return incrementToken; }
+
+// attributes
+ ExpressionNode *base;
+ SourceLocation incrementToken;
+};
+
+class PostDecrementExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(PostDecrementExpression)
+
+ PostDecrementExpression(ExpressionNode *b):
+ base (b) { kind = K; }
+
+ virtual ~PostDecrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return decrementToken; }
+
+// attributes
+ ExpressionNode *base;
+ SourceLocation decrementToken;
+};
+
+class DeleteExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(DeleteExpression)
+
+ DeleteExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+ virtual ~DeleteExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return deleteToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation deleteToken;
+};
+
+class VoidExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(VoidExpression)
+
+ VoidExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~VoidExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return voidToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation voidToken;
+};
+
+class TypeOfExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(TypeOfExpression)
+
+ TypeOfExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~TypeOfExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return typeofToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation typeofToken;
+};
+
+class PreIncrementExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(PreIncrementExpression)
+
+ PreIncrementExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~PreIncrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return incrementToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation incrementToken;
+};
+
+class PreDecrementExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(PreDecrementExpression)
+
+ PreDecrementExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~PreDecrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return decrementToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation decrementToken;
+};
+
+class UnaryPlusExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UnaryPlusExpression)
+
+ UnaryPlusExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~UnaryPlusExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return plusToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation plusToken;
+};
+
+class UnaryMinusExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UnaryMinusExpression)
+
+ UnaryMinusExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~UnaryMinusExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return minusToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation minusToken;
+};
+
+class TildeExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(TildeExpression)
+
+ TildeExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~TildeExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return tildeToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation tildeToken;
+};
+
+class NotExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(NotExpression)
+
+ NotExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~NotExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return notToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation notToken;
+};
+
+class BinaryExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(BinaryExpression)
+
+ BinaryExpression(ExpressionNode *l, int o, ExpressionNode *r):
+ left (l), op (o), right (r)
+ { kind = K; }
+
+ virtual ~BinaryExpression() {}
+
+ virtual BinaryExpression *binaryExpressionCast();
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return left->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return right->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *left;
+ int op;
+ ExpressionNode *right;
+ SourceLocation operatorToken;
+};
+
+class ConditionalExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ConditionalExpression)
+
+ ConditionalExpression(ExpressionNode *e, ExpressionNode *t, ExpressionNode *f):
+ expression (e), ok (t), ko (f)
+ { kind = K; }
+
+ virtual ~ConditionalExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return expression->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return ko->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ ExpressionNode *ok;
+ ExpressionNode *ko;
+ SourceLocation questionToken;
+ SourceLocation colonToken;
+};
+
+class Expression: public ExpressionNode // ### rename
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(Expression)
+
+ Expression(ExpressionNode *l, ExpressionNode *r):
+ left (l), right (r) { kind = K; }
+
+ virtual ~Expression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return left->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return right->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *left;
+ ExpressionNode *right;
+ SourceLocation commaToken;
+};
+
+class Block: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(Block)
+
+ Block(StatementList *slist):
+ statements (slist) { kind = K; }
+
+ virtual ~Block() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbraceToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbraceToken; }
+
+ // attributes
+ StatementList *statements;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class StatementList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(StatementList)
+
+ StatementList(Statement *stmt):
+ statement (stmt), next (this)
+ { kind = K; }
+
+ StatementList(StatementList *previous, Statement *stmt):
+ statement (stmt)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~StatementList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline StatementList *finish ()
+ {
+ StatementList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ Statement *statement;
+ StatementList *next;
+};
+
+class VariableStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(VariableStatement)
+
+ VariableStatement(VariableDeclarationList *vlist):
+ declarations (vlist)
+ { kind = K; }
+
+ virtual ~VariableStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return declarationKindToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ VariableDeclarationList *declarations;
+ SourceLocation declarationKindToken;
+ SourceLocation semicolonToken;
+};
+
+class VariableDeclaration: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(VariableDeclaration)
+
+ VariableDeclaration(JavaScriptNameIdImpl *n, ExpressionNode *e):
+ name (n), expression (e), readOnly(false)
+ { kind = K; }
+
+ virtual ~VariableDeclaration() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ JavaScriptNameIdImpl *name;
+ ExpressionNode *expression;
+ bool readOnly;
+ SourceLocation identifierToken;
+};
+
+class VariableDeclarationList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(VariableDeclarationList)
+
+ VariableDeclarationList(VariableDeclaration *decl):
+ declaration (decl), next (this)
+ { kind = K; }
+
+ VariableDeclarationList(VariableDeclarationList *previous, VariableDeclaration *decl):
+ declaration (decl)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~VariableDeclarationList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline VariableDeclarationList *finish (bool readOnly)
+ {
+ VariableDeclarationList *front = next;
+ next = 0;
+ if (readOnly) {
+ VariableDeclarationList *vdl;
+ for (vdl = front; vdl != 0; vdl = vdl->next)
+ vdl->declaration->readOnly = true;
+ }
+ return front;
+ }
+
+// attributes
+ VariableDeclaration *declaration;
+ VariableDeclarationList *next;
+ SourceLocation commaToken;
+};
+
+class EmptyStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(EmptyStatement)
+
+ EmptyStatement() { kind = K; }
+ virtual ~EmptyStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return semicolonToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ SourceLocation semicolonToken;
+};
+
+class ExpressionStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ExpressionStatement)
+
+ ExpressionStatement(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~ExpressionStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return expression->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation semicolonToken;
+};
+
+class IfStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(IfStatement)
+
+ IfStatement(ExpressionNode *e, Statement *t, Statement *f = 0):
+ expression (e), ok (t), ko (f)
+ { kind = K; }
+
+ virtual ~IfStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return ifToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (ko)
+ return ko->lastSourceLocation();
+
+ return ok->lastSourceLocation();
+ }
+
+// attributes
+ ExpressionNode *expression;
+ Statement *ok;
+ Statement *ko;
+ SourceLocation ifToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+ SourceLocation elseToken;
+};
+
+class DoWhileStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(DoWhileStatement)
+
+ DoWhileStatement(Statement *stmt, ExpressionNode *e):
+ statement (stmt), expression (e)
+ { kind = K; }
+
+ virtual ~DoWhileStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return doToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ Statement *statement;
+ ExpressionNode *expression;
+ SourceLocation doToken;
+ SourceLocation whileToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+ SourceLocation semicolonToken;
+};
+
+class WhileStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(WhileStatement)
+
+ WhileStatement(ExpressionNode *e, Statement *stmt):
+ expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~WhileStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return whileToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation whileToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class ForStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ForStatement)
+
+ ForStatement(ExpressionNode *i, ExpressionNode *c, ExpressionNode *e, Statement *stmt):
+ initialiser (i), condition (c), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~ForStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *initialiser;
+ ExpressionNode *condition;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation firstSemicolonToken;
+ SourceLocation secondSemicolonToken;
+ SourceLocation rparenToken;
+};
+
+class LocalForStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(LocalForStatement)
+
+ LocalForStatement(VariableDeclarationList *vlist, ExpressionNode *c, ExpressionNode *e, Statement *stmt):
+ declarations (vlist), condition (c), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~LocalForStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ VariableDeclarationList *declarations;
+ ExpressionNode *condition;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation varToken;
+ SourceLocation firstSemicolonToken;
+ SourceLocation secondSemicolonToken;
+ SourceLocation rparenToken;
+};
+
+class ForEachStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ForEachStatement)
+
+ ForEachStatement(ExpressionNode *i, ExpressionNode *e, Statement *stmt):
+ initialiser (i), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~ForEachStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *initialiser;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation inToken;
+ SourceLocation rparenToken;
+};
+
+class LocalForEachStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(LocalForEachStatement)
+
+ LocalForEachStatement(VariableDeclaration *v, ExpressionNode *e, Statement *stmt):
+ declaration (v), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~LocalForEachStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ VariableDeclaration *declaration;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation varToken;
+ SourceLocation inToken;
+ SourceLocation rparenToken;
+};
+
+class ContinueStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ContinueStatement)
+
+ ContinueStatement(JavaScriptNameIdImpl *l = 0):
+ label (l) { kind = K; }
+
+ virtual ~ContinueStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return continueToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ JavaScriptNameIdImpl *label;
+ SourceLocation continueToken;
+ SourceLocation identifierToken;
+ SourceLocation semicolonToken;
+};
+
+class BreakStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(BreakStatement)
+
+ BreakStatement(JavaScriptNameIdImpl *l = 0):
+ label (l) { kind = K; }
+
+ virtual ~BreakStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return breakToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+ // attributes
+ JavaScriptNameIdImpl *label;
+ SourceLocation breakToken;
+ SourceLocation identifierToken;
+ SourceLocation semicolonToken;
+};
+
+class ReturnStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ReturnStatement)
+
+ ReturnStatement(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~ReturnStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return returnToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation returnToken;
+ SourceLocation semicolonToken;
+};
+
+class WithStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(WithStatement)
+
+ WithStatement(ExpressionNode *e, Statement *stmt):
+ expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~WithStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return withToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation withToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class CaseBlock: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(CaseBlock)
+
+ CaseBlock(CaseClauses *c, DefaultClause *d = 0, CaseClauses *r = 0):
+ clauses (c), defaultClause (d), moreClauses (r)
+ { kind = K; }
+
+ virtual ~CaseBlock() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ CaseClauses *clauses;
+ DefaultClause *defaultClause;
+ CaseClauses *moreClauses;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class SwitchStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(SwitchStatement)
+
+ SwitchStatement(ExpressionNode *e, CaseBlock *b):
+ expression (e), block (b)
+ { kind = K; }
+
+ virtual ~SwitchStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return switchToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return block->rbraceToken; }
+
+// attributes
+ ExpressionNode *expression;
+ CaseBlock *block;
+ SourceLocation switchToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class CaseClauses: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(CaseClauses)
+
+ CaseClauses(CaseClause *c):
+ clause (c), next (this)
+ { kind = K; }
+
+ CaseClauses(CaseClauses *previous, CaseClause *c):
+ clause (c)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~CaseClauses() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline CaseClauses *finish ()
+ {
+ CaseClauses *front = next;
+ next = 0;
+ return front;
+ }
+
+//attributes
+ CaseClause *clause;
+ CaseClauses *next;
+};
+
+class CaseClause: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(CaseClause)
+
+ CaseClause(ExpressionNode *e, StatementList *slist):
+ expression (e), statements (slist)
+ { kind = K; }
+
+ virtual ~CaseClause() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ ExpressionNode *expression;
+ StatementList *statements;
+ SourceLocation caseToken;
+ SourceLocation colonToken;
+};
+
+class DefaultClause: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(DefaultClause)
+
+ DefaultClause(StatementList *slist):
+ statements (slist)
+ { kind = K; }
+
+ virtual ~DefaultClause() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ StatementList *statements;
+ SourceLocation defaultToken;
+ SourceLocation colonToken;
+};
+
+class LabelledStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(LabelledStatement)
+
+ LabelledStatement(JavaScriptNameIdImpl *l, Statement *stmt):
+ label (l), statement (stmt)
+ { kind = K; }
+
+ virtual ~LabelledStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ JavaScriptNameIdImpl *label;
+ Statement *statement;
+ SourceLocation identifierToken;
+ SourceLocation colonToken;
+};
+
+class ThrowStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(ThrowStatement)
+
+ ThrowStatement(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~ThrowStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return throwToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+ // attributes
+ ExpressionNode *expression;
+ SourceLocation throwToken;
+ SourceLocation semicolonToken;
+};
+
+class Catch: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(Catch)
+
+ Catch(JavaScriptNameIdImpl *n, Block *stmt):
+ name (n), statement (stmt)
+ { kind = K; }
+
+ virtual ~Catch() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ JavaScriptNameIdImpl *name;
+ Block *statement;
+ SourceLocation catchToken;
+ SourceLocation lparenToken;
+ SourceLocation identifierToken;
+ SourceLocation rparenToken;
+};
+
+class Finally: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(Finally)
+
+ Finally(Block *stmt):
+ statement (stmt)
+ { kind = K; }
+
+ virtual ~Finally() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Block *statement;
+ SourceLocation finallyToken;
+};
+
+class TryStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(TryStatement)
+
+ TryStatement(Statement *stmt, Catch *c, Finally *f):
+ statement (stmt), catchExpression (c), finallyExpression (f)
+ { kind = K; }
+
+ TryStatement(Statement *stmt, Finally *f):
+ statement (stmt), catchExpression (0), finallyExpression (f)
+ { kind = K; }
+
+ TryStatement(Statement *stmt, Catch *c):
+ statement (stmt), catchExpression (c), finallyExpression (0)
+ { kind = K; }
+
+ virtual ~TryStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return tryToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (finallyExpression)
+ return finallyExpression->statement->rbraceToken;
+ else if (catchExpression)
+ return catchExpression->statement->rbraceToken;
+
+ return statement->lastSourceLocation();
+ }
+
+// attributes
+ Statement *statement;
+ Catch *catchExpression;
+ Finally *finallyExpression;
+ SourceLocation tryToken;
+};
+
+class FunctionExpression: public ExpressionNode
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FunctionExpression)
+
+ FunctionExpression(JavaScriptNameIdImpl *n, FormalParameterList *f, FunctionBody *b):
+ name (n), formals (f), body (b)
+ { kind = K; }
+
+ virtual ~FunctionExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return functionToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbraceToken; }
+
+// attributes
+ JavaScriptNameIdImpl *name;
+ FormalParameterList *formals;
+ FunctionBody *body;
+ SourceLocation functionToken;
+ SourceLocation identifierToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class FunctionDeclaration: public FunctionExpression
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FunctionDeclaration)
+
+ FunctionDeclaration(JavaScriptNameIdImpl *n, FormalParameterList *f, FunctionBody *b):
+ FunctionExpression(n, f, b)
+ { kind = K; }
+
+ virtual ~FunctionDeclaration() {}
+
+ virtual void accept0(Visitor *visitor);
+};
+
+class FormalParameterList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FormalParameterList)
+
+ FormalParameterList(JavaScriptNameIdImpl *n):
+ name (n), next (this)
+ { kind = K; }
+
+ FormalParameterList(FormalParameterList *previous, JavaScriptNameIdImpl *n):
+ name (n)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~FormalParameterList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline FormalParameterList *finish ()
+ {
+ FormalParameterList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ JavaScriptNameIdImpl *name;
+ FormalParameterList *next;
+ SourceLocation commaToken;
+ SourceLocation identifierToken;
+};
+
+class FunctionBody: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FunctionBody)
+
+ FunctionBody(SourceElements *elts):
+ elements (elts)
+ { kind = K; }
+
+ virtual ~FunctionBody() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceElements *elements;
+};
+
+class Program: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(Program)
+
+ Program(SourceElements *elts):
+ elements (elts)
+ { kind = K; }
+
+ virtual ~Program() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceElements *elements;
+};
+
+class SourceElements: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(SourceElements)
+
+ SourceElements(SourceElement *elt):
+ element (elt), next (this)
+ { kind = K; }
+
+ SourceElements(SourceElements *previous, SourceElement *elt):
+ element (elt)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~SourceElements() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline SourceElements *finish ()
+ {
+ SourceElements *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ SourceElement *element;
+ SourceElements *next;
+};
+
+class SourceElement: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(SourceElement)
+
+ inline SourceElement()
+ { kind = K; }
+
+ virtual ~SourceElement() {}
+};
+
+class FunctionSourceElement: public SourceElement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(FunctionSourceElement)
+
+ FunctionSourceElement(FunctionDeclaration *f):
+ declaration (f)
+ { kind = K; }
+
+ virtual ~FunctionSourceElement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ FunctionDeclaration *declaration;
+};
+
+class StatementSourceElement: public SourceElement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(StatementSourceElement)
+
+ StatementSourceElement(Statement *stmt):
+ statement (stmt)
+ { kind = K; }
+
+ virtual ~StatementSourceElement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Statement *statement;
+};
+
+class DebuggerStatement: public Statement
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(DebuggerStatement)
+
+ DebuggerStatement()
+ { kind = K; }
+
+ virtual ~DebuggerStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return debuggerToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ SourceLocation debuggerToken;
+ SourceLocation semicolonToken;
+};
+
+class UiProgram: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiProgram)
+
+ UiProgram(UiImportList *imports, UiObjectMemberList *members)
+ : imports(imports), members(members)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiImportList *imports;
+ UiObjectMemberList *members;
+};
+
+class UiQualifiedId: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiQualifiedId)
+
+ UiQualifiedId(JavaScriptNameIdImpl *name)
+ : next(this), name(name)
+ { kind = K; }
+
+ UiQualifiedId(UiQualifiedId *previous, JavaScriptNameIdImpl *name)
+ : name(name)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~UiQualifiedId() {}
+
+ UiQualifiedId *finish()
+ {
+ UiQualifiedId *head = next;
+ next = 0;
+ return head;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *next;
+ JavaScriptNameIdImpl *name;
+ SourceLocation identifierToken;
+};
+
+class UiImport: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiImport)
+
+ UiImport(JavaScriptNameIdImpl *fileName)
+ : fileName(fileName)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ JavaScriptNameIdImpl *fileName;
+ SourceLocation importToken;
+ SourceLocation fileNameToken;
+ SourceLocation semicolonToken;
+};
+
+class UiImportList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiImportList)
+
+ UiImportList(UiImport *import)
+ : import(import),
+ next(this)
+ { kind = K; }
+
+ UiImportList(UiImportList *previous, UiImport *import)
+ : import(import)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ UiImportList *finish()
+ {
+ UiImportList *head = next;
+ next = 0;
+ return head;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiImport *import;
+ UiImportList *next;
+};
+
+class UiObjectMember: public Node
+{
+public:
+ virtual SourceLocation firstSourceLocation() const = 0;
+ virtual SourceLocation lastSourceLocation() const = 0;
+};
+
+class UiObjectMemberList: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiObjectMemberList)
+
+ UiObjectMemberList(UiObjectMember *member)
+ : next(this), member(member)
+ { kind = K; }
+
+ UiObjectMemberList(UiObjectMemberList *previous, UiObjectMember *member)
+ : member(member)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+ UiObjectMemberList *finish()
+ {
+ UiObjectMemberList *head = next;
+ next = 0;
+ return head;
+ }
+
+// attributes
+ UiObjectMemberList *next;
+ UiObjectMember *member;
+};
+
+class UiObjectInitializer: public Node
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiObjectInitializer)
+
+ UiObjectInitializer(UiObjectMemberList *members)
+ : members(members)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceLocation lbraceToken;
+ UiObjectMemberList *members;
+ SourceLocation rbraceToken;
+};
+
+class UiPublicMember: public UiObjectMember
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiPublicMember)
+
+ UiPublicMember(JavaScriptNameIdImpl *memberType,
+ JavaScriptNameIdImpl *name)
+ : type(Property), memberType(memberType), name(name), expression(0), isDefaultMember(false)
+ { kind = K; }
+
+ UiPublicMember(JavaScriptNameIdImpl *memberType,
+ JavaScriptNameIdImpl *name,
+ ExpressionNode *expression)
+ : type(Property), memberType(memberType), name(name), expression(expression), isDefaultMember(false)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ {
+ if (defaultToken.isValid())
+ return defaultToken;
+
+ return propertyToken;
+ }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ return semicolonToken;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ enum { Signal, Property } type;
+ JavaScriptNameIdImpl *memberType;
+ JavaScriptNameIdImpl *name;
+ ExpressionNode *expression;
+ bool isDefaultMember;
+ SourceLocation defaultToken;
+ SourceLocation propertyToken;
+ SourceLocation typeToken;
+ SourceLocation identifierToken;
+ SourceLocation colonToken;
+ SourceLocation semicolonToken;
+};
+
+class UiObjectDefinition: public UiObjectMember
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiObjectDefinition)
+
+ UiObjectDefinition(JavaScriptNameIdImpl *name,
+ UiObjectInitializer *initializer)
+ : name(name), initializer(initializer)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (initializer)
+ return initializer->rbraceToken;
+
+ return identifierToken;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ JavaScriptNameIdImpl *name;
+ UiObjectInitializer *initializer;
+ SourceLocation identifierToken;
+};
+
+class UiSourceElement: public UiObjectMember
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiSourceElement)
+
+ UiSourceElement(Node *sourceElement)
+ : sourceElement(sourceElement)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ {
+ if (FunctionDeclaration *funDecl = cast<FunctionDeclaration *>(sourceElement))
+ return funDecl->firstSourceLocation();
+ else if (VariableStatement *varStmt = cast<VariableStatement *>(sourceElement))
+ return varStmt->firstSourceLocation();
+
+ return SourceLocation();
+ }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (FunctionDeclaration *funDecl = cast<FunctionDeclaration *>(sourceElement))
+ return funDecl->lastSourceLocation();
+ else if (VariableStatement *varStmt = cast<VariableStatement *>(sourceElement))
+ return varStmt->lastSourceLocation();
+
+ return SourceLocation();
+ }
+
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Node *sourceElement;
+};
+
+class UiObjectBinding: public UiObjectMember
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiObjectBinding)
+
+ UiObjectBinding(UiQualifiedId *qualifiedId,
+ JavaScriptNameIdImpl *name,
+ UiObjectInitializer *initializer)
+ : qualifiedId(qualifiedId),
+ name(name),
+ initializer(initializer)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return initializer->rbraceToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ JavaScriptNameIdImpl *name;
+ UiObjectInitializer *initializer;
+ SourceLocation colonToken;
+ SourceLocation identifierToken;
+};
+
+class UiScriptBinding: public UiObjectMember
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiScriptBinding)
+
+ UiScriptBinding(UiQualifiedId *qualifiedId,
+ Statement *statement)
+ : qualifiedId(qualifiedId),
+ statement(statement)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ Statement *statement;
+ SourceLocation colonToken;
+};
+
+class UiArrayBinding: public UiObjectMember
+{
+public:
+ JAVASCRIPT_DECLARE_AST_NODE(UiArrayBinding)
+
+ UiArrayBinding(UiQualifiedId *qualifiedId,
+ UiObjectMemberList *members)
+ : qualifiedId(qualifiedId),
+ members(members)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbracketToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ UiObjectMemberList *members;
+ SourceLocation colonToken;
+ SourceLocation lbracketToken;
+ SourceLocation rbracketToken;
+};
+
+} } // namespace AST
+
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/javascriptastfwd_p.h b/src/declarative/qml/parser/javascriptastfwd_p.h
new file mode 100644
index 0000000..858e393
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptastfwd_p.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTAST_FWD_P_H
+#define JAVASCRIPTAST_FWD_P_H
+
+#include <QtCore/qglobal.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript { namespace AST {
+
+class SourceLocation;
+
+class Visitor;
+class Node;
+class ExpressionNode;
+class Statement;
+class ThisExpression;
+class IdentifierExpression;
+class NullExpression;
+class TrueLiteral;
+class FalseLiteral;
+class NumericLiteral;
+class StringLiteral;
+class RegExpLiteral;
+class ArrayLiteral;
+class ObjectLiteral;
+class ElementList;
+class Elision;
+class PropertyNameAndValueList;
+class PropertyName;
+class IdentifierPropertyName;
+class StringLiteralPropertyName;
+class NumericLiteralPropertyName;
+class ArrayMemberExpression;
+class FieldMemberExpression;
+class NewMemberExpression;
+class NewExpression;
+class CallExpression;
+class ArgumentList;
+class PostIncrementExpression;
+class PostDecrementExpression;
+class DeleteExpression;
+class VoidExpression;
+class TypeOfExpression;
+class PreIncrementExpression;
+class PreDecrementExpression;
+class UnaryPlusExpression;
+class UnaryMinusExpression;
+class TildeExpression;
+class NotExpression;
+class BinaryExpression;
+class ConditionalExpression;
+class Expression; // ### rename
+class Block;
+class StatementList;
+class VariableStatement;
+class VariableDeclarationList;
+class VariableDeclaration;
+class EmptyStatement;
+class ExpressionStatement;
+class IfStatement;
+class DoWhileStatement;
+class WhileStatement;
+class ForStatement;
+class LocalForStatement;
+class ForEachStatement;
+class LocalForEachStatement;
+class ContinueStatement;
+class BreakStatement;
+class ReturnStatement;
+class WithStatement;
+class SwitchStatement;
+class CaseBlock;
+class CaseClauses;
+class CaseClause;
+class DefaultClause;
+class LabelledStatement;
+class ThrowStatement;
+class TryStatement;
+class Catch;
+class Finally;
+class FunctionDeclaration;
+class FunctionExpression;
+class FormalParameterList;
+class FunctionBody;
+class Program;
+class SourceElements;
+class SourceElement;
+class FunctionSourceElement;
+class StatementSourceElement;
+class DebuggerStatement;
+class NestedExpression;
+
+// ui elements
+class UiProgram;
+class UiImportList;
+class UiImport;
+class UiPublicMember;
+class UiObjectDefinition;
+class UiObjectInitializer;
+class UiObjectBinding;
+class UiScriptBinding;
+class UiSourceElement;
+class UiArrayBinding;
+class UiObjectMember;
+class UiObjectMemberList;
+class UiQualifiedId;
+
+} } // namespace AST
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/javascriptastvisitor.cpp b/src/declarative/qml/parser/javascriptastvisitor.cpp
new file mode 100644
index 0000000..eac291d
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptastvisitor.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "javascriptastvisitor_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript { namespace AST {
+
+Visitor::Visitor()
+{
+}
+
+Visitor::~Visitor()
+{
+}
+
+} } // namespace JavaScript::AST
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/parser/javascriptastvisitor_p.h b/src/declarative/qml/parser/javascriptastvisitor_p.h
new file mode 100644
index 0000000..81df364
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptastvisitor_p.h
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTASTVISITOR_P_H
+#define JAVASCRIPTASTVISITOR_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 "javascriptastfwd_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript { namespace AST {
+
+class Visitor
+{
+public:
+ Visitor();
+ virtual ~Visitor();
+
+ virtual bool preVisit(Node *) { return true; }
+ virtual void postVisit(Node *) {}
+
+ // Ui
+ virtual bool visit(UiProgram *) { return true; }
+ virtual bool visit(UiImportList *) { return true; }
+ virtual bool visit(UiImport *) { return true; }
+ virtual bool visit(UiPublicMember *) { return true; }
+ virtual bool visit(UiSourceElement *) { return true; }
+ virtual bool visit(UiObjectDefinition *) { return true; }
+ virtual bool visit(UiObjectInitializer *) { return true; }
+ virtual bool visit(UiObjectBinding *) { return true; }
+ virtual bool visit(UiScriptBinding *) { return true; }
+ virtual bool visit(UiArrayBinding *) { return true; }
+ virtual bool visit(UiObjectMemberList *) { return true; }
+ virtual bool visit(UiQualifiedId *) { return true; }
+
+ virtual void endVisit(UiProgram *) {}
+ virtual void endVisit(UiImportList *) {}
+ virtual void endVisit(UiImport *) {}
+ virtual void endVisit(UiPublicMember *) {}
+ virtual void endVisit(UiSourceElement *) {}
+ virtual void endVisit(UiObjectDefinition *) {}
+ virtual void endVisit(UiObjectInitializer *) {}
+ virtual void endVisit(UiObjectBinding *) {}
+ virtual void endVisit(UiScriptBinding *) {}
+ virtual void endVisit(UiArrayBinding *) {}
+ virtual void endVisit(UiObjectMemberList *) {}
+ virtual void endVisit(UiQualifiedId *) {}
+
+ // JavaScript
+ virtual bool visit(ThisExpression *) { return true; }
+ virtual void endVisit(ThisExpression *) {}
+
+ virtual bool visit(IdentifierExpression *) { return true; }
+ virtual void endVisit(IdentifierExpression *) {}
+
+ virtual bool visit(NullExpression *) { return true; }
+ virtual void endVisit(NullExpression *) {}
+
+ virtual bool visit(TrueLiteral *) { return true; }
+ virtual void endVisit(TrueLiteral *) {}
+
+ virtual bool visit(FalseLiteral *) { return true; }
+ virtual void endVisit(FalseLiteral *) {}
+
+ virtual bool visit(StringLiteral *) { return true; }
+ virtual void endVisit(StringLiteral *) {}
+
+ virtual bool visit(NumericLiteral *) { return true; }
+ virtual void endVisit(NumericLiteral *) {}
+
+ virtual bool visit(RegExpLiteral *) { return true; }
+ virtual void endVisit(RegExpLiteral *) {}
+
+ virtual bool visit(ArrayLiteral *) { return true; }
+ virtual void endVisit(ArrayLiteral *) {}
+
+ virtual bool visit(ObjectLiteral *) { return true; }
+ virtual void endVisit(ObjectLiteral *) {}
+
+ virtual bool visit(ElementList *) { return true; }
+ virtual void endVisit(ElementList *) {}
+
+ virtual bool visit(Elision *) { return true; }
+ virtual void endVisit(Elision *) {}
+
+ virtual bool visit(PropertyNameAndValueList *) { return true; }
+ virtual void endVisit(PropertyNameAndValueList *) {}
+
+ virtual bool visit(NestedExpression *) { return true; }
+ virtual void endVisit(NestedExpression *) {}
+
+ virtual bool visit(IdentifierPropertyName *) { return true; }
+ virtual void endVisit(IdentifierPropertyName *) {}
+
+ virtual bool visit(StringLiteralPropertyName *) { return true; }
+ virtual void endVisit(StringLiteralPropertyName *) {}
+
+ virtual bool visit(NumericLiteralPropertyName *) { return true; }
+ virtual void endVisit(NumericLiteralPropertyName *) {}
+
+ virtual bool visit(ArrayMemberExpression *) { return true; }
+ virtual void endVisit(ArrayMemberExpression *) {}
+
+ virtual bool visit(FieldMemberExpression *) { return true; }
+ virtual void endVisit(FieldMemberExpression *) {}
+
+ virtual bool visit(NewMemberExpression *) { return true; }
+ virtual void endVisit(NewMemberExpression *) {}
+
+ virtual bool visit(NewExpression *) { return true; }
+ virtual void endVisit(NewExpression *) {}
+
+ virtual bool visit(CallExpression *) { return true; }
+ virtual void endVisit(CallExpression *) {}
+
+ virtual bool visit(ArgumentList *) { return true; }
+ virtual void endVisit(ArgumentList *) {}
+
+ virtual bool visit(PostIncrementExpression *) { return true; }
+ virtual void endVisit(PostIncrementExpression *) {}
+
+ virtual bool visit(PostDecrementExpression *) { return true; }
+ virtual void endVisit(PostDecrementExpression *) {}
+
+ virtual bool visit(DeleteExpression *) { return true; }
+ virtual void endVisit(DeleteExpression *) {}
+
+ virtual bool visit(VoidExpression *) { return true; }
+ virtual void endVisit(VoidExpression *) {}
+
+ virtual bool visit(TypeOfExpression *) { return true; }
+ virtual void endVisit(TypeOfExpression *) {}
+
+ virtual bool visit(PreIncrementExpression *) { return true; }
+ virtual void endVisit(PreIncrementExpression *) {}
+
+ virtual bool visit(PreDecrementExpression *) { return true; }
+ virtual void endVisit(PreDecrementExpression *) {}
+
+ virtual bool visit(UnaryPlusExpression *) { return true; }
+ virtual void endVisit(UnaryPlusExpression *) {}
+
+ virtual bool visit(UnaryMinusExpression *) { return true; }
+ virtual void endVisit(UnaryMinusExpression *) {}
+
+ virtual bool visit(TildeExpression *) { return true; }
+ virtual void endVisit(TildeExpression *) {}
+
+ virtual bool visit(NotExpression *) { return true; }
+ virtual void endVisit(NotExpression *) {}
+
+ virtual bool visit(BinaryExpression *) { return true; }
+ virtual void endVisit(BinaryExpression *) {}
+
+ virtual bool visit(ConditionalExpression *) { return true; }
+ virtual void endVisit(ConditionalExpression *) {}
+
+ virtual bool visit(Expression *) { return true; }
+ virtual void endVisit(Expression *) {}
+
+ virtual bool visit(Block *) { return true; }
+ virtual void endVisit(Block *) {}
+
+ virtual bool visit(StatementList *) { return true; }
+ virtual void endVisit(StatementList *) {}
+
+ virtual bool visit(VariableStatement *) { return true; }
+ virtual void endVisit(VariableStatement *) {}
+
+ virtual bool visit(VariableDeclarationList *) { return true; }
+ virtual void endVisit(VariableDeclarationList *) {}
+
+ virtual bool visit(VariableDeclaration *) { return true; }
+ virtual void endVisit(VariableDeclaration *) {}
+
+ virtual bool visit(EmptyStatement *) { return true; }
+ virtual void endVisit(EmptyStatement *) {}
+
+ virtual bool visit(ExpressionStatement *) { return true; }
+ virtual void endVisit(ExpressionStatement *) {}
+
+ virtual bool visit(IfStatement *) { return true; }
+ virtual void endVisit(IfStatement *) {}
+
+ virtual bool visit(DoWhileStatement *) { return true; }
+ virtual void endVisit(DoWhileStatement *) {}
+
+ virtual bool visit(WhileStatement *) { return true; }
+ virtual void endVisit(WhileStatement *) {}
+
+ virtual bool visit(ForStatement *) { return true; }
+ virtual void endVisit(ForStatement *) {}
+
+ virtual bool visit(LocalForStatement *) { return true; }
+ virtual void endVisit(LocalForStatement *) {}
+
+ virtual bool visit(ForEachStatement *) { return true; }
+ virtual void endVisit(ForEachStatement *) {}
+
+ virtual bool visit(LocalForEachStatement *) { return true; }
+ virtual void endVisit(LocalForEachStatement *) {}
+
+ virtual bool visit(ContinueStatement *) { return true; }
+ virtual void endVisit(ContinueStatement *) {}
+
+ virtual bool visit(BreakStatement *) { return true; }
+ virtual void endVisit(BreakStatement *) {}
+
+ virtual bool visit(ReturnStatement *) { return true; }
+ virtual void endVisit(ReturnStatement *) {}
+
+ virtual bool visit(WithStatement *) { return true; }
+ virtual void endVisit(WithStatement *) {}
+
+ virtual bool visit(SwitchStatement *) { return true; }
+ virtual void endVisit(SwitchStatement *) {}
+
+ virtual bool visit(CaseBlock *) { return true; }
+ virtual void endVisit(CaseBlock *) {}
+
+ virtual bool visit(CaseClauses *) { return true; }
+ virtual void endVisit(CaseClauses *) {}
+
+ virtual bool visit(CaseClause *) { return true; }
+ virtual void endVisit(CaseClause *) {}
+
+ virtual bool visit(DefaultClause *) { return true; }
+ virtual void endVisit(DefaultClause *) {}
+
+ virtual bool visit(LabelledStatement *) { return true; }
+ virtual void endVisit(LabelledStatement *) {}
+
+ virtual bool visit(ThrowStatement *) { return true; }
+ virtual void endVisit(ThrowStatement *) {}
+
+ virtual bool visit(TryStatement *) { return true; }
+ virtual void endVisit(TryStatement *) {}
+
+ virtual bool visit(Catch *) { return true; }
+ virtual void endVisit(Catch *) {}
+
+ virtual bool visit(Finally *) { return true; }
+ virtual void endVisit(Finally *) {}
+
+ virtual bool visit(FunctionDeclaration *) { return true; }
+ virtual void endVisit(FunctionDeclaration *) {}
+
+ virtual bool visit(FunctionExpression *) { return true; }
+ virtual void endVisit(FunctionExpression *) {}
+
+ virtual bool visit(FormalParameterList *) { return true; }
+ virtual void endVisit(FormalParameterList *) {}
+
+ virtual bool visit(FunctionBody *) { return true; }
+ virtual void endVisit(FunctionBody *) {}
+
+ virtual bool visit(Program *) { return true; }
+ virtual void endVisit(Program *) {}
+
+ virtual bool visit(SourceElements *) { return true; }
+ virtual void endVisit(SourceElements *) {}
+
+ virtual bool visit(FunctionSourceElement *) { return true; }
+ virtual void endVisit(FunctionSourceElement *) {}
+
+ virtual bool visit(StatementSourceElement *) { return true; }
+ virtual void endVisit(StatementSourceElement *) {}
+
+ virtual bool visit(DebuggerStatement *) { return true; }
+ virtual void endVisit(DebuggerStatement *) {}
+};
+
+} } // namespace AST
+
+QT_END_NAMESPACE
+
+#endif // JAVASCRIPTASTVISITOR_P_H
diff --git a/src/declarative/qml/parser/javascriptengine_p.cpp b/src/declarative/qml/parser/javascriptengine_p.cpp
new file mode 100644
index 0000000..ca15b75
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptengine_p.cpp
@@ -0,0 +1,157 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#include "javascriptengine_p.h"
+#include "javascriptnodepool_p.h"
+#include "javascriptvalue.h"
+#include <qnumeric.h>
+#include <QHash>
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript {
+
+QString numberToString(qjsreal value)
+{ return QString::number(value); }
+
+int Ecma::RegExp::flagFromChar(const QChar &ch)
+{
+ static QHash<QChar, int> flagsHash;
+ if (flagsHash.isEmpty()) {
+ flagsHash[QLatin1Char('g')] = Global;
+ flagsHash[QLatin1Char('i')] = IgnoreCase;
+ flagsHash[QLatin1Char('m')] = Multiline;
+ }
+ QHash<QChar, int>::const_iterator it;
+ it = flagsHash.constFind(ch);
+ if (it == flagsHash.constEnd())
+ return 0;
+ return it.value();
+}
+
+QString Ecma::RegExp::flagsToString(int flags)
+{
+ QString result;
+ if (flags & Global)
+ result += QLatin1Char('g');
+ if (flags & IgnoreCase)
+ result += QLatin1Char('i');
+ if (flags & Multiline)
+ result += QLatin1Char('m');
+ return result;
+}
+
+NodePool::NodePool(const QString &fileName, JavaScriptEnginePrivate *engine)
+ : m_fileName(fileName), m_engine(engine)
+{
+}
+
+NodePool::~NodePool()
+{
+}
+
+Code *NodePool::createCompiledCode(AST::Node *, CompilationUnit &)
+{
+ Q_ASSERT(0);
+ return 0;
+}
+
+static int toDigit(char c)
+{
+ if ((c >= '0') && (c <= '9'))
+ return c - '0';
+ else if ((c >= 'a') && (c <= 'z'))
+ return 10 + c - 'a';
+ else if ((c >= 'A') && (c <= 'Z'))
+ return 10 + c - 'A';
+ return -1;
+}
+
+qjsreal integerFromString(const char *buf, int size, int radix)
+{
+ if (size == 0)
+ return qSNaN();
+
+ qjsreal sign = 1.0;
+ int i = 0;
+ if (buf[0] == '+') {
+ ++i;
+ } else if (buf[0] == '-') {
+ sign = -1.0;
+ ++i;
+ }
+
+ if (((size-i) >= 2) && (buf[i] == '0')) {
+ if (((buf[i+1] == 'x') || (buf[i+1] == 'X'))
+ && (radix < 34)) {
+ if ((radix != 0) && (radix != 16))
+ return 0;
+ radix = 16;
+ i += 2;
+ } else {
+ if (radix == 0) {
+ radix = 8;
+ ++i;
+ }
+ }
+ } else if (radix == 0) {
+ radix = 10;
+ }
+
+ int j = i;
+ for ( ; i < size; ++i) {
+ int d = toDigit(buf[i]);
+ if ((d == -1) || (d >= radix))
+ break;
+ }
+ qjsreal result;
+ if (j == i) {
+ if (!qstrcmp(buf, "Infinity"))
+ result = qInf();
+ else
+ result = qSNaN();
+ } else {
+ result = 0;
+ qjsreal multiplier = 1;
+ for (--i ; i >= j; --i, multiplier *= radix)
+ result += toDigit(buf[i]) * multiplier;
+ }
+ result *= sign;
+ return result;
+}
+
+qjsreal integerFromString(const QString &str, int radix)
+{
+ QByteArray ba = str.trimmed().toUtf8();
+ return integerFromString(ba.constData(), ba.size(), radix);
+}
+
+} // end of namespace JavaScript
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/parser/javascriptengine_p.h b/src/declarative/qml/parser/javascriptengine_p.h
new file mode 100644
index 0000000..1e6e568
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptengine_p.h
@@ -0,0 +1,144 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+**************************************************************************/
+
+#ifndef JAVASCRIPTENGINE_P_H
+#define JAVASCRIPTENGINE_P_H
+
+#include "javascriptvalue.h"
+#include <QString>
+#include <QSet>
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript {
+
+class Node;
+class Lexer;
+class NodePool;
+
+namespace AST {
+
+class Node;
+
+} // end of namespace AST
+
+namespace Ecma {
+
+class RegExp
+{
+public:
+ enum RegExpFlag {
+ Global = 0x01,
+ IgnoreCase = 0x02,
+ Multiline = 0x04
+ };
+
+public:
+ static int flagFromChar(const QChar &);
+ static QString flagsToString(int flags);
+};
+
+} // end of namespace Ecma
+
+} // end of namespace JavaScript
+
+
+
+class JavaScriptNameIdImpl
+{
+ QString _text;
+
+public:
+ JavaScriptNameIdImpl(const QChar *u, int s)
+ : _text(u, s)
+ { }
+
+ const QString asString() const
+ { return _text; }
+
+ bool operator == (const JavaScriptNameIdImpl &other) const
+ { return _text == other._text; }
+
+ bool operator != (const JavaScriptNameIdImpl &other) const
+ { return _text != other._text; }
+
+ bool operator < (const JavaScriptNameIdImpl &other) const
+ { return _text < other._text; }
+};
+
+inline uint qHash(const JavaScriptNameIdImpl &id)
+{ return qHash(id.asString()); }
+
+class JavaScriptEnginePrivate
+{
+ JavaScript::Lexer *_lexer;
+ JavaScript::NodePool *_nodePool;
+ JavaScript::AST::Node *_ast;
+ QSet<JavaScriptNameIdImpl> _literals;
+
+public:
+ JavaScriptEnginePrivate()
+ : _lexer(0), _nodePool(0), _ast(0)
+ { }
+
+ QSet<JavaScriptNameIdImpl> literals() const
+ { return _literals; }
+
+ JavaScriptNameIdImpl *intern(const QChar *u, int s)
+ { return const_cast<JavaScriptNameIdImpl *>(&*_literals.insert(JavaScriptNameIdImpl(u, s))); }
+
+ static QString toString(JavaScriptNameIdImpl *id)
+ { return id->asString(); }
+
+ JavaScript::Lexer *lexer() const
+ { return _lexer; }
+
+ void setLexer(JavaScript::Lexer *lexer)
+ { _lexer = lexer; }
+
+ JavaScript::NodePool *nodePool() const
+ { return _nodePool; }
+
+ void setNodePool(JavaScript::NodePool *nodePool)
+ { _nodePool = nodePool; }
+
+ JavaScript::AST::Node *ast() const
+ { return _ast; }
+
+ JavaScript::AST::Node *changeAbstractSyntaxTree(JavaScript::AST::Node *node)
+ {
+ JavaScript::AST::Node *previousAST = _ast;
+ _ast = node;
+ return previousAST;
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // JAVASCRIPTENGINE_P_H
diff --git a/src/declarative/qml/parser/javascriptgrammar.cpp b/src/declarative/qml/parser/javascriptgrammar.cpp
new file mode 100644
index 0000000..abe3f1c
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptgrammar.cpp
@@ -0,0 +1,732 @@
+// This file was generated by qlalr - DO NOT EDIT!
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "javascriptgrammar_p.h"
+
+const char *const JavaScriptGrammar::spell [] = {
+ "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ";", "continue",
+ "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===",
+ "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier",
+ "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=",
+ "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=",
+ "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return",
+ ")", ";", 0, "*", "*=", "string literal", "property", "signal", "switch", "this",
+ "throw", "~", "try", "typeof", "var", "void", "while", "with", "^", "^=",
+ "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "public", "import", 0,
+ 0};
+
+const int JavaScriptGrammar::lhs [] = {
+ 91, 92, 92, 95, 95, 96, 96, 94, 93, 98,
+ 98, 100, 100, 101, 101, 99, 97, 99, 99, 103,
+ 104, 104, 99, 99, 106, 106, 106, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 102, 102,
+ 110, 110, 110, 102, 102, 111, 111, 111, 111, 111,
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111,
+ 113, 113, 117, 117, 112, 112, 115, 115, 118, 118,
+ 118, 118, 118, 118, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
+ 119, 119, 119, 119, 119, 120, 120, 121, 121, 121,
+ 121, 121, 124, 124, 125, 125, 125, 125, 123, 123,
+ 126, 126, 127, 127, 128, 128, 128, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 130, 130, 130,
+ 130, 131, 131, 131, 132, 132, 132, 132, 133, 133,
+ 133, 133, 133, 133, 133, 134, 134, 134, 134, 134,
+ 134, 135, 135, 135, 135, 135, 136, 136, 136, 136,
+ 136, 137, 137, 138, 138, 139, 139, 140, 140, 141,
+ 141, 142, 142, 143, 143, 144, 144, 145, 145, 146,
+ 146, 147, 147, 148, 148, 116, 116, 149, 149, 150,
+ 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
+ 150, 107, 107, 151, 151, 152, 152, 153, 153, 105,
+ 105, 105, 105, 105, 105, 105, 105, 105, 105, 105,
+ 105, 105, 105, 105, 154, 169, 169, 168, 168, 109,
+ 109, 170, 170, 171, 171, 173, 173, 172, 174, 177,
+ 175, 175, 178, 176, 176, 155, 156, 156, 157, 157,
+ 158, 158, 158, 158, 158, 158, 158, 159, 159, 159,
+ 159, 160, 160, 160, 160, 161, 161, 162, 164, 179,
+ 179, 182, 182, 180, 180, 183, 181, 163, 163, 163,
+ 165, 165, 166, 166, 166, 184, 185, 167, 167, 108,
+ 122, 189, 189, 186, 186, 187, 187, 190, 191, 191,
+ 192, 192, 188, 188, 114, 114, 193};
+
+const int JavaScriptGrammar:: rhs[] = {
+ 2, 1, 1, 1, 2, 3, 3, 0, 1, 1,
+ 2, 1, 3, 2, 3, 4, 2, 1, 5, 1,
+ 2, 2, 3, 3, 1, 1, 1, 2, 4, 4,
+ 5, 5, 6, 6, 7, 7, 1, 1, 1, 1,
+ 1, 1, 1, 1, 3, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 3, 3, 5, 3, 4, 3,
+ 2, 4, 1, 2, 0, 1, 3, 5, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 4,
+ 3, 5, 1, 2, 4, 4, 4, 3, 0, 1,
+ 1, 3, 1, 1, 1, 2, 2, 1, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 1, 3, 3,
+ 3, 1, 3, 3, 1, 3, 3, 3, 1, 3,
+ 3, 3, 3, 3, 3, 1, 3, 3, 3, 3,
+ 3, 1, 3, 3, 3, 3, 1, 3, 3, 3,
+ 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
+ 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
+ 3, 1, 5, 1, 5, 1, 3, 1, 3, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 3, 0, 1, 1, 3, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 3, 1, 2, 0, 1, 3,
+ 3, 1, 1, 1, 3, 1, 3, 2, 2, 2,
+ 0, 1, 2, 0, 1, 1, 2, 2, 7, 5,
+ 7, 7, 5, 9, 10, 7, 8, 2, 2, 3,
+ 3, 2, 2, 3, 3, 3, 3, 5, 5, 3,
+ 5, 1, 2, 0, 1, 4, 3, 3, 3, 3,
+ 3, 3, 3, 3, 4, 5, 2, 2, 2, 8,
+ 8, 1, 3, 0, 1, 0, 1, 1, 1, 2,
+ 1, 1, 0, 1, 0, 1, 2};
+
+const int JavaScriptGrammar::action_default [] = {
+ 8, 2, 0, 4, 3, 0, 0, 0, 6, 7,
+ 5, 0, 9, 1, 0, 17, 37, 44, 242, 0,
+ 0, 41, 42, 14, 39, 40, 43, 243, 18, 10,
+ 0, 0, 0, 38, 0, 27, 26, 25, 0, 0,
+ 31, 0, 32, 145, 212, 176, 184, 180, 124, 196,
+ 172, 0, 109, 47, 125, 188, 192, 113, 142, 123,
+ 128, 108, 162, 149, 0, 53, 54, 50, 313, 41,
+ 315, 65, 0, 0, 0, 0, 0, 48, 51, 0,
+ 0, 42, 43, 52, 46, 0, 49, 0, 0, 138,
+ 0, 0, 125, 144, 127, 126, 0, 0, 0, 140,
+ 141, 139, 143, 0, 173, 0, 0, 0, 0, 163,
+ 0, 0, 0, 0, 0, 0, 153, 0, 0, 0,
+ 147, 148, 146, 151, 155, 154, 152, 150, 165, 164,
+ 166, 0, 181, 0, 177, 0, 0, 119, 106, 118,
+ 107, 75, 76, 77, 102, 78, 103, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 104, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 101, 105, 0, 0, 117, 213, 120, 0, 121, 0,
+ 122, 116, 35, 36, 0, 209, 202, 200, 207, 208,
+ 206, 205, 211, 204, 203, 201, 210, 197, 0, 185,
+ 0, 0, 189, 0, 0, 193, 0, 0, 119, 111,
+ 0, 110, 0, 115, 129, 0, 314, 304, 305, 0,
+ 302, 0, 303, 0, 306, 220, 227, 226, 234, 222,
+ 0, 223, 307, 0, 312, 224, 225, 230, 228, 309,
+ 308, 311, 231, 0, 0, 0, 0, 0, 313, 41,
+ 0, 315, 42, 214, 256, 43, 0, 0, 0, 0,
+ 0, 232, 233, 221, 229, 257, 258, 301, 310, 0,
+ 272, 273, 274, 275, 0, 268, 269, 270, 271, 298,
+ 299, 0, 0, 0, 0, 0, 261, 262, 218, 216,
+ 178, 186, 182, 198, 174, 219, 0, 125, 190, 194,
+ 167, 156, 0, 0, 175, 0, 0, 0, 0, 168,
+ 0, 0, 0, 0, 0, 160, 158, 161, 159, 157,
+ 170, 169, 171, 0, 183, 0, 179, 0, 217, 125,
+ 0, 199, 214, 215, 0, 214, 0, 0, 264, 0,
+ 0, 0, 266, 0, 187, 0, 0, 191, 0, 0,
+ 195, 254, 0, 246, 255, 249, 0, 253, 0, 214,
+ 247, 0, 214, 0, 0, 265, 0, 0, 0, 267,
+ 314, 304, 0, 0, 306, 0, 300, 0, 290, 0,
+ 0, 0, 260, 0, 259, 0, 316, 0, 74, 236,
+ 239, 0, 75, 242, 78, 103, 80, 81, 50, 85,
+ 86, 41, 87, 90, 48, 51, 42, 214, 43, 52,
+ 93, 46, 95, 49, 97, 98, 243, 100, 101, 105,
+ 0, 67, 0, 0, 69, 73, 71, 59, 70, 72,
+ 0, 68, 58, 237, 235, 113, 114, 119, 0, 112,
+ 0, 289, 0, 276, 277, 0, 288, 0, 0, 0,
+ 279, 284, 282, 285, 0, 0, 283, 284, 0, 280,
+ 0, 281, 238, 287, 0, 238, 286, 0, 291, 292,
+ 0, 238, 293, 294, 0, 0, 295, 0, 0, 0,
+ 296, 297, 131, 130, 0, 0, 0, 263, 0, 0,
+ 0, 278, 0, 66, 0, 63, 65, 56, 0, 62,
+ 57, 64, 61, 55, 0, 60, 135, 133, 137, 134,
+ 132, 136, 0, 0, 0, 29, 0, 30, 0, 33,
+ 34, 28, 15, 11, 0, 0, 24, 41, 65, 20,
+ 0, 23, 16, 0, 12, 0, 19, 13, 21, 22,
+ 45, 251, 244, 0, 252, 248, 0, 250, 240, 0,
+ 241, 245, 317};
+
+const int JavaScriptGrammar::goto_default [] = {
+ 6, 5, 13, 1, 4, 3, 28, 30, 29, 533,
+ 15, 31, 530, 531, 389, 513, 230, 234, 263, 53,
+ 61, 494, 492, 387, 386, 44, 493, 385, 388, 139,
+ 57, 52, 177, 59, 48, 176, 54, 60, 89, 58,
+ 43, 63, 62, 300, 50, 294, 45, 290, 47, 292,
+ 46, 291, 55, 298, 56, 299, 49, 293, 289, 330,
+ 442, 295, 296, 225, 229, 231, 235, 236, 227, 226,
+ 238, 264, 237, 242, 261, 262, 228, 391, 390, 32,
+ 543, 542, 352, 353, 545, 355, 544, 354, 450, 454,
+ 457, 453, 452, 472, 473, 219, 233, 215, 218, 232,
+ 240, 239, 0};
+
+const int JavaScriptGrammar::action_index [] = {
+ -23, -91, 10, -91, -19, 50, 77, 56, -91, -91,
+ -91, 67, -91, -91, 383, -91, -91, -91, -91, -4,
+ 213, 20, 186, -91, -91, -91, -18, -91, -91, -91,
+ 370, 129, 203, -91, 204, -91, -91, -91, -17, 192,
+ -91, 693, -91, 87, -91, 42, 9, -20, 191, -91,
+ 310, 140, -91, -91, 534, 17, 114, 160, 125, -91,
+ -91, -91, 344, 162, 693, -91, -91, -91, 157, -91,
+ 1191, 34, 693, 693, 693, 613, 693, -91, -91, 693,
+ 693, -91, -91, -91, -91, 693, -91, 693, 693, -91,
+ 693, 693, 119, 227, -91, -91, 693, 693, 693, -91,
+ -91, -91, 193, 693, 310, 693, 693, 693, 693, 446,
+ 693, 693, 693, 693, 693, 693, 237, 693, 693, 693,
+ 88, 106, 107, 237, 237, 166, 237, 237, 354, 372,
+ 334, 693, -11, 693, 19, 1104, 693, 693, -91, -91,
+ -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
+ -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
+ -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
+ -91, -91, 98, 693, -91, -91, 0, -43, -91, 693,
+ -91, -91, -91, -91, 693, -91, -91, -91, -91, -91,
+ -91, -91, -91, -91, -91, -91, -91, -91, 693, 6,
+ 693, 693, -2, 82, 693, -91, 1104, 693, 693, -91,
+ 96, -91, 8, -91, -91, 61, -91, 147, 80, 33,
+ -91, 154, -91, 63, 1452, -91, -91, -91, -91, -91,
+ 169, -91, -91, 23, -91, -91, -91, -91, -91, -91,
+ 1452, -91, -91, 285, 287, 68, 1365, 55, 112, 79,
+ 46, 1626, 66, 693, -91, 65, 47, 693, 52, 58,
+ 59, -91, -91, -91, -91, -91, -91, -91, -91, 64,
+ -91, -91, -91, -91, 73, -91, -91, -91, -91, -91,
+ -91, -5, 45, 693, 137, 81, -91, -91, 1017, -91,
+ 69, 28, 14, -91, 240, 76, 53, 476, 171, 120,
+ 308, 237, 180, 693, 264, 693, 693, 693, 693, 298,
+ 693, 693, 693, 693, 693, 230, 237, 237, 237, 237,
+ 288, 268, 378, 693, -68, 693, 12, 693, -91, 445,
+ 693, -91, 693, 7, -47, 693, -44, 1365, -91, 693,
+ 100, 1365, -91, 693, -25, 693, 693, 22, 15, 693,
+ -91, -8, 108, -13, -91, -91, 693, -91, 178, 693,
+ -91, -60, 693, -58, 1365, -91, 693, 99, 1365, -91,
+ -33, 199, -53, -27, 1452, -26, -91, 1365, -91, 693,
+ 95, 1365, 32, 1365, -91, 43, 41, 4, -91, -91,
+ 1365, 5, 232, 54, 275, 70, 693, 1365, 49, 27,
+ 252, 48, 30, 613, 40, 39, -91, 777, -91, 25,
+ -1, 26, 693, 24, -3, 693, 21, 693, 1, 2,
+ 693, -91, 1278, 37, -91, -91, -91, -91, -91, -91,
+ 693, -91, -91, -91, -91, 156, -91, 693, -21, -91,
+ 1365, -91, 60, -91, -91, 1365, -91, 693, 102, 3,
+ -91, 29, -91, 35, 101, 693, -91, 36, 38, -91,
+ -30, -91, 1365, -91, 94, 1365, -91, 176, -91, -91,
+ 143, 1365, 44, -91, 16, -6, -91, 207, -9, -29,
+ -91, -91, -91, -91, 693, 90, 1365, -91, 693, 91,
+ 1365, -91, 111, 13, 857, -91, 18, -91, 937, -91,
+ -91, -91, -91, -91, 105, -91, -91, -91, -91, -91,
+ -91, -91, -33, -24, 215, -91, 693, -91, 187, -91,
+ -91, -91, -91, -91, 1539, 174, -91, 133, 104, -91,
+ 62, -91, -91, 97, -91, 51, -91, -91, -91, -91,
+ -91, 57, -91, 173, -91, -91, 693, -91, -91, 151,
+ -91, -91, -91,
+
+ -103, -103, -103, -103, 15, 16, -103, -103, -103, -103,
+ -103, -103, -103, -103, 208, -103, -103, -103, -103, -103,
+ -1, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ 237, -103, 26, -103, 31, -103, -103, -103, -103, -103,
+ -103, 28, -103, -103, -103, -103, -103, -103, -103, -103,
+ -103, -103, -103, -103, -46, -103, -103, -103, -103, -103,
+ -103, -103, -103, -103, 98, -103, -103, -103, 7, -103,
+ -103, -103, -10, 118, 111, 67, 112, -103, -103, 119,
+ 123, -103, -103, -103, -103, 124, -103, 115, 97, -103,
+ 32, 106, -103, -103, -103, -103, 128, 171, 101, -103,
+ -103, -103, -103, 156, -103, 157, 159, 81, 131, -103,
+ 127, 136, 145, 139, 102, 91, -103, 59, 50, 72,
+ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ -103, 70, -103, 80, -103, 85, 61, 51, -103, -103,
+ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ -103, -103, -103, 54, -103, -103, -103, -103, -103, -24,
+ -103, -103, -103, -103, -23, -103, -103, -103, -103, -103,
+ -103, -103, -103, -103, -103, -103, -103, -103, 134, -103,
+ 138, 17, -103, -103, 23, -103, 255, -4, 73, -103,
+ -103, -103, -103, -103, -103, -103, -103, 11, -103, -103,
+ -103, 8, -103, -103, 9, -103, -103, -103, -103, -103,
+ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ 77, -103, -103, 10, 2, -103, 5, -103, -3, -103,
+ -103, -103, -103, 19, -103, -103, -103, 27, -31, -103,
+ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ -103, -103, -103, -5, -103, -103, -103, -103, 105, -103,
+ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ -103, -103, 34, 205, -103, 193, 169, 181, 201, -103,
+ 147, 66, 78, 79, 89, -103, -103, -103, -103, -103,
+ -103, -103, -103, 202, -103, 192, -103, 212, -103, -103,
+ 182, -103, 68, -103, -103, 62, -103, 56, -103, 33,
+ -103, 55, -103, 170, -103, 161, 162, -103, -103, 172,
+ -103, -103, -103, -103, -103, -103, 211, -103, 69, 71,
+ -103, -103, 64, -103, 60, -103, 41, -103, 42, -103,
+ -103, 74, -103, -103, 75, -103, -103, 38, -103, 35,
+ -103, 36, -103, 44, -103, -103, -103, -103, -103, -103,
+ 52, -103, 45, -103, 43, -103, 65, 46, -103, -103,
+ 40, -103, -103, 146, -103, -103, -103, 49, -103, -103,
+ -103, -103, 47, -103, -22, 149, -103, 153, -103, -103,
+ 30, -103, 48, -103, -103, -103, -103, -103, -103, -103,
+ 29, -103, -103, -103, -103, -103, -103, 133, -103, -103,
+ 53, -103, -103, -103, -103, 58, -103, 57, -103, -103,
+ -103, -103, -103, -56, -103, -6, -103, -82, -103, -103,
+ -103, -103, -77, -103, -103, -68, -103, -103, -103, -103,
+ -103, -103, -90, -103, -103, -58, -103, -11, -103, -60,
+ -103, -103, -103, -103, 21, -103, 25, -103, 22, -103,
+ 20, -103, -103, -103, 6, -103, 12, -103, 3, -103,
+ -103, -103, -103, -103, -103, -103, -103, -103, -103, -103,
+ -103, -103, -103, -103, -103, -103, 24, -103, -103, -103,
+ -103, -103, -103, -103, 1, -2, -103, 4, 104, -103,
+ -103, -103, -103, -103, -103, 18, -103, -103, -103, -103,
+ -103, -103, -103, -103, -103, -103, 0, -103, -103, 63,
+ -103, -103, -103};
+
+const int JavaScriptGrammar::action_info [] = {
+ 198, 362, 364, 371, 471, 514, 374, 373, 179, 356,
+ 325, 521, 39, 303, 335, 173, 337, 181, 366, 198,
+ 103, 501, 349, 323, 343, 461, 495, 471, -99, 376,
+ 471, -96, -72, -94, 455, 447, 451, 484, 488, 439,
+ 455, 455, 495, 103, 430, 462, -73, -91, 383, 422,
+ 420, 479, 477, 14, 131, -69, -83, 131, 133, 432,
+ 434, -102, 34, 288, 475, 2, 379, 133, 213, 2,
+ 303, 282, 445, 440, 546, 7, 323, 552, 267, 11,
+ 11, 283, 379, 447, 327, 471, 377, 0, 221, 204,
+ 0, 288, 325, 223, 484, 488, 224, 217, 173, 173,
+ 14, 465, 173, 173, 173, 535, 173, 173, 173, 0,
+ 173, 458, 495, 173, 332, 0, 358, 9, 8, 496,
+ 0, 444, 443, 539, 538, 273, 272, 90, 90, 280,
+ 279, 280, 279, 11, 278, 277, 524, 96, 91, 91,
+ 377, 69, 287, 286, 525, 173, 90, 90, 173, 474,
+ 486, 490, 211, 536, 174, 381, 459, 91, 91, 368,
+ 341, 94, 449, 475, 200, 505, 14, 497, 201, 359,
+ 345, 206, 95, 343, 346, 206, 69, 173, 81, 82,
+ 69, 549, 97, 69, 173, 0, 69, 117, 98, 118,
+ 207, 117, 437, 118, 207, 173, 208, 285, 0, 41,
+ 119, 183, 182, 69, 119, 96, 135, 69, 0, 69,
+ 0, 0, 0, 81, 82, 35, 0, 81, 82, 0,
+ 81, 82, 516, 81, 82, 136, 0, 137, 69, 0,
+ 266, 265, 69, 35, 550, 548, 69, 469, 468, 96,
+ 81, 82, 69, 0, 81, 82, 81, 82, 520, 519,
+ 97, 0, 0, 42, 40, 117, 98, 118, 305, 306,
+ 37, 69, 117, 0, 118, 81, 82, 0, 119, 81,
+ 82, 36, 0, 81, 82, 119, 517, 515, 37, 81,
+ 82, 69, 305, 306, 97, 307, 308, 0, -313, 36,
+ 98, 310, 311, 271, 270, 0, 0, 0, 81, 82,
+ 312, 0, 0, 313, 69, 314, 0, 0, 0, 307,
+ 308, 310, 311, 0, 69, 0, 69, 0, 81, 82,
+ 312, 310, 311, 313, 0, 314, 0, 0, 105, 106,
+ 312, 310, 311, 313, 0, 314, 276, 275, 0, 0,
+ 312, 81, 82, 313, 0, 314, 271, 270, 276, 275,
+ 0, 81, 82, 81, 82, 107, 108, 110, 111, 0,
+ 0, 0, 0, 0, 0, 112, 113, 110, 111, 114,
+ 0, 115, 0, 0, 0, 112, 113, 110, 111, 114,
+ 19, 115, 0, 0, 0, 112, 113, 0, 0, 114,
+ 0, 115, 20, 19, 0, 110, 111, 0, 0, 21,
+ 0, 310, 311, 112, 113, 20, 0, 114, 0, 115,
+ 312, 0, 21, 313, 0, 314, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 522, 0, 0, 0, 25,
+ 0, 0, 0, 0, 0, 0, 22, 26, 23, 0,
+ 0, 0, 25, 0, 27, 0, 0, 0, 185, 22,
+ 26, 0, 0, 18, 0, 24, 0, 27, 186, 0,
+ 0, 0, 187, 0, 0, 0, 18, 0, 24, 110,
+ 111, 188, 0, 189, 0, 0, 0, 112, 113, 185,
+ 0, 114, 0, 115, 190, 0, 191, 94, 0, 186,
+ 0, 0, 0, 187, 192, 0, 0, 193, 95, 0,
+ 0, 0, 188, 194, 189, 0, 0, 339, 0, 195,
+ 0, 0, 0, 0, 0, 190, 0, 191, 94, 0,
+ 0, 0, 0, 0, 196, 192, 0, 0, 193, 95,
+ 0, 0, 0, 0, 194, 0, 0, 185, 0, 0,
+ 195, 0, 0, 0, 0, 0, 0, 186, 0, 0,
+ 0, 187, 0, 0, 0, 196, 0, 0, 0, 0,
+ 188, 0, 189, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 190, 0, 191, 94, 0, 0, 0,
+ 0, 0, 0, 192, 0, 0, 193, 95, 0, 0,
+ 0, 0, 194, 0, 0, 0, 0, 0, 195, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 196, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 65, 66, 0, 0, 0,
+ 0, 0, 0, 0, 0, 68, 0, 0, 0, 0,
+ 0, 0, 69, 0, 0, 0, 70, 71, 0, 72,
+ 0, 0, 0, 0, 0, 0, 75, 0, 0, 0,
+ 78, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 83, 81,
+ 82, 0, 84, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 77, 86, 67, 0, 0, 0, 0,
+ 0, 0, 0, 0, 64, 65, 66, 0, 0, 0,
+ 0, 0, 0, 0, 0, 68, 0, 0, 0, 0,
+ 0, 0, 69, 0, 0, 0, 70, 71, 0, 72,
+ 0, 0, 0, 73, 0, 74, 75, 76, 0, 0,
+ 78, 0, 0, 0, 79, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 83, 81,
+ 82, 0, 84, 0, 85, 0, 87, 0, 88, 0,
+ 0, 0, 0, 77, 86, 67, 0, 0, 0, 0,
+ 0, 0, 0, 0, -92, 0, 0, 0, 64, 65,
+ 66, 0, 0, 0, 0, 0, 0, 0, 0, 68,
+ 0, 0, 0, 0, 0, 0, 69, 0, 0, 0,
+ 70, 71, 0, 72, 0, 0, 0, 73, 0, 74,
+ 75, 76, 0, 0, 78, 0, 0, 0, 79, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 83, 81, 82, 0, 84, 0, 85, 0,
+ 87, 0, 88, 0, 0, 0, 0, 77, 86, 67,
+ 0, 0, 0, 0, 0, 0, 0, 0, 64, 65,
+ 66, 0, 0, 0, 0, 0, 0, 0, 0, 68,
+ 0, 0, 0, 0, 0, 0, 69, 0, 0, 0,
+ 70, 71, 0, 72, 0, 0, 0, 73, 0, 74,
+ 75, 76, 0, 0, 78, 0, 0, 0, 79, 0,
+ 80, 0, 0, 503, 0, 0, 0, 0, 0, 0,
+ 0, 0, 83, 81, 82, 0, 84, 0, 85, 0,
+ 87, 0, 88, 0, 0, 0, 0, 77, 86, 67,
+ 0, 0, 0, 0, 0, 0, 0, 0, 64, 65,
+ 66, 0, 0, 0, 0, 0, 0, 0, 0, 68,
+ 0, 0, 0, 0, 0, 0, 69, 0, 0, 0,
+ 70, 71, 0, 72, 0, 0, 0, 73, 0, 74,
+ 75, 76, 0, 0, 78, 0, 0, 0, 79, 0,
+ 80, 0, 0, 500, 0, 0, 0, 0, 0, 0,
+ 0, 0, 83, 81, 82, 0, 84, 0, 85, 0,
+ 87, 0, 88, 0, 0, 0, 0, 77, 86, 67,
+ 0, 0, 0, 0, 0, 0, 0, 0, 64, 65,
+ 66, 0, 0, 0, 0, 0, 0, 0, 0, 68,
+ 0, 0, 0, 0, 0, 0, 69, 0, 0, 0,
+ 70, 71, 0, 72, 0, 0, 0, 73, 0, 74,
+ 75, 76, 0, 0, 78, 0, 0, 0, 79, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 83, 81, 82, 0, 84, 0, 85, 0,
+ 87, 302, 88, 0, 0, 0, 0, 77, 86, 67,
+ 0, 0, 0, 0, 0, 0, 0, 0, 141, 142,
+ 143, 0, 0, 145, 147, 148, 0, 0, 149, 0,
+ 150, 0, 0, 0, 152, 153, 154, 0, 0, 0,
+ 0, 0, 0, 69, 155, 156, 157, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 158, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 161, 0, 0, 0, 0, 0, 0,
+ 81, 82, 162, 163, 164, 0, 166, 167, 168, 169,
+ 170, 171, 0, 0, 159, 165, 151, 144, 146, 160,
+ 0, 0, 0, 0, 0, 141, 142, 143, 0, 0,
+ 145, 147, 148, 0, 0, 149, 0, 150, 0, 0,
+ 0, 152, 153, 154, 0, 0, 0, 0, 0, 0,
+ 424, 155, 156, 157, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 158, 0, 0, 0, 425, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 161, 0, 0, 0, 0, 0, 429, 426, 428, 162,
+ 163, 164, 0, 166, 167, 168, 169, 170, 171, 0,
+ 0, 159, 165, 151, 144, 146, 160, 0, 0, 0,
+ 0, 0, 141, 142, 143, 0, 0, 145, 147, 148,
+ 0, 0, 149, 0, 150, 0, 0, 0, 152, 153,
+ 154, 0, 0, 0, 0, 0, 0, 424, 155, 156,
+ 157, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 158, 0, 0, 0, 425, 0, 0, 0, 0,
+ 0, 0, 0, 427, 0, 0, 0, 161, 0, 0,
+ 0, 0, 0, 429, 426, 428, 162, 163, 164, 0,
+ 166, 167, 168, 169, 170, 171, 0, 0, 159, 165,
+ 151, 144, 146, 160, 0, 0, 0, 0, 0, 243,
+ 0, 0, 0, 0, 244, 0, 64, 65, 66, 246,
+ 0, 0, 0, 0, 0, 0, 247, 68, 0, 0,
+ 0, 0, 0, 0, 249, 250, 0, 0, 251, 71,
+ 0, 72, 0, 0, 0, 73, 0, 74, 75, 76,
+ 0, 0, 78, 0, 0, 0, 79, 0, 80, 0,
+ 0, 0, 0, 0, 253, 0, 254, 0, 0, 0,
+ 83, 252, 255, 256, 84, 257, 85, 258, 87, 27,
+ 88, 259, 260, 0, 0, 77, 86, 67, 18, 245,
+ 0, 0, 0, 0, 0, 0, 243, 0, 0, 0,
+ 0, 244, 0, 64, 65, 66, 246, 0, 0, 0,
+ 0, 0, 0, 247, 248, 0, 0, 0, 0, 0,
+ 0, 249, 250, 0, 0, 251, 71, 0, 72, 0,
+ 0, 0, 73, 0, 74, 75, 76, 0, 0, 78,
+ 0, 0, 0, 79, 0, 80, 0, 0, 0, 0,
+ 0, 253, 0, 254, 0, 0, 0, 83, 252, 255,
+ 256, 84, 257, 85, 258, 87, 27, 88, 259, 260,
+ 0, 0, 77, 86, 67, 18, 245, 0, 0, 0,
+ 0, 0, 0, 243, 0, 0, 0, 0, 244, 0,
+ 64, 65, 66, 246, 0, 0, 0, 0, 0, 0,
+ 247, 68, 0, 0, 0, 0, 0, 0, 527, 250,
+ 0, 0, 251, 528, 0, 72, 0, 0, 0, 73,
+ 0, 74, 75, 76, 0, 0, 78, 0, 0, 0,
+ 79, 0, 80, 0, 0, 0, 0, 0, 253, 0,
+ 254, 0, 0, 0, 83, 252, 255, 256, 84, 257,
+ 85, 258, 87, 27, 88, 259, 260, 0, 0, 77,
+ 86, 67, 18, 245, 0, 529, 0, 0, 0, 0,
+ 392, 142, 143, 0, 0, 394, 147, 396, 65, 66,
+ 397, 0, 150, 0, 0, 0, 152, 399, 400, 0,
+ 0, 0, 0, 0, 0, 401, 402, 156, 157, 251,
+ 71, 0, 72, 0, 0, 0, 73, 0, 74, 403,
+ 76, 0, 0, 405, 0, 0, 0, 79, 0, 80,
+ 0, -238, 0, 0, 0, 407, 0, 254, 0, 0,
+ 0, 409, 406, 408, 410, 411, 412, 85, 414, 415,
+ 416, 417, 418, 419, 0, 0, 404, 413, 398, 393,
+ 395, 160, 0, 0, 0, 0, 0,
+
+ 463, 180, 197, 480, 476, 481, 504, 460, 478, 466,
+ 464, 284, 210, 184, 532, 526, 370, 540, 512, 281,
+ 10, 274, 12, 241, 537, 547, 216, 222, 499, 269,
+ 220, 502, 470, 498, 491, 333, 456, 485, 489, 487,
+ 518, 470, 203, 467, 51, 541, 38, 0, 205, 340,
+ 382, 380, 378, 351, 431, 421, 369, 367, 384, 216,
+ 281, 0, 274, 467, 269, 333, 433, 441, 92, 342,
+ 338, 93, 446, 448, 365, 423, 178, 172, 333, 175,
+ 333, 0, 541, 0, 333, 0, 92, 333, 351, 241,
+ 121, 241, 0, 220, 0, 92, 0, 435, 178, 120,
+ 436, 92, 92, 214, 138, 212, 92, 316, 92, 0,
+ 534, 0, 122, 140, 92, 92, 92, 92, 132, 317,
+ 318, 0, 336, 129, 363, 92, 134, 92, 334, 0,
+ 319, 361, 127, 92, 92, 483, 214, 92, 92, 101,
+ 0, 297, 92, 126, 551, 102, 301, 92, 92, 507,
+ 508, 92, 360, 482, 92, 92, 506, 509, 178, 92,
+ 92, 510, 511, 92, 92, 438, 99, 92, 116, 372,
+ 92, 375, 92, 130, 92, 92, 435, 123, 268, 436,
+ 125, 92, 0, 92, 199, 92, 124, 482, 315, 92,
+ 202, 483, 92, 92, 0, 92, 0, 92, 329, 109,
+ 104, 128, 301, 301, 0, 92, 92, 92, 329, 100,
+ 301, 301, 320, 301, 347, 0, 0, 92, 329, 0,
+ 348, 344, 301, 301, 321, 16, 33, 17, 92, 92,
+ 350, 0, 0, 301, 301, 0, 309, 92, 92, 326,
+ 331, 92, 301, 301, 322, 523, 301, 329, 329, 0,
+ 304, 324, 301, 301, 16, 33, 17, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 357,
+ 328, 0, 0, 0, 138, 0, 0, 0, 0, 0,
+ 0, 0, 0, 140, 209, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+
+const int JavaScriptGrammar::action_check [] = {
+ 2, 61, 60, 36, 33, 29, 33, 60, 8, 17,
+ 78, 29, 29, 1, 61, 8, 60, 60, 31, 2,
+ 1, 8, 7, 48, 2, 55, 8, 33, 7, 55,
+ 33, 7, 7, 7, 5, 36, 33, 36, 36, 60,
+ 5, 5, 8, 1, 7, 7, 7, 7, 16, 8,
+ 7, 60, 36, 33, 48, 7, 7, 48, 78, 55,
+ 55, 7, 66, 36, 20, 88, 36, 78, 60, 88,
+ 1, 76, 7, 7, 17, 65, 48, 0, 55, 29,
+ 29, 36, 36, 36, 8, 33, 7, -1, 8, 7,
+ -1, 36, 78, 60, 36, 36, 33, 36, 8, 8,
+ 33, 7, 8, 8, 8, 8, 8, 8, 8, -1,
+ 8, 10, 8, 8, 61, -1, 8, 61, 62, 8,
+ -1, 61, 62, 61, 62, 61, 62, 40, 40, 61,
+ 62, 61, 62, 29, 61, 62, 7, 12, 51, 51,
+ 7, 29, 61, 62, 15, 8, 40, 40, 8, 6,
+ 60, 60, 56, 56, 56, 60, 55, 51, 51, 60,
+ 60, 42, 60, 20, 50, 60, 33, 56, 54, 61,
+ 50, 15, 53, 2, 54, 15, 29, 8, 66, 67,
+ 29, 8, 57, 29, 8, -1, 29, 25, 63, 27,
+ 34, 25, 36, 27, 34, 8, 36, 60, -1, 7,
+ 38, 61, 62, 29, 38, 12, 15, 29, -1, 29,
+ -1, -1, -1, 66, 67, 29, -1, 66, 67, -1,
+ 66, 67, 7, 66, 67, 34, -1, 36, 29, -1,
+ 61, 62, 29, 29, 61, 62, 29, 61, 62, 12,
+ 66, 67, 29, -1, 66, 67, 66, 67, 61, 62,
+ 57, -1, -1, 61, 62, 25, 63, 27, 18, 19,
+ 74, 29, 25, -1, 27, 66, 67, -1, 38, 66,
+ 67, 85, -1, 66, 67, 38, 61, 62, 74, 66,
+ 67, 29, 18, 19, 57, 45, 46, -1, 36, 85,
+ 63, 23, 24, 61, 62, -1, -1, -1, 66, 67,
+ 32, -1, -1, 35, 29, 37, -1, -1, -1, 45,
+ 46, 23, 24, -1, 29, -1, 29, -1, 66, 67,
+ 32, 23, 24, 35, -1, 37, -1, -1, 18, 19,
+ 32, 23, 24, 35, -1, 37, 61, 62, -1, -1,
+ 32, 66, 67, 35, -1, 37, 61, 62, 61, 62,
+ -1, 66, 67, 66, 67, 45, 46, 23, 24, -1,
+ -1, -1, -1, -1, -1, 31, 32, 23, 24, 35,
+ -1, 37, -1, -1, -1, 31, 32, 23, 24, 35,
+ 10, 37, -1, -1, -1, 31, 32, -1, -1, 35,
+ -1, 37, 22, 10, -1, 23, 24, -1, -1, 29,
+ -1, 23, 24, 31, 32, 22, -1, 35, -1, 37,
+ 32, -1, 29, 35, -1, 37, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 55, -1, -1, -1, 59,
+ -1, -1, -1, -1, -1, -1, 66, 67, 55, -1,
+ -1, -1, 59, -1, 74, -1, -1, -1, 3, 66,
+ 67, -1, -1, 83, -1, 85, -1, 74, 13, -1,
+ -1, -1, 17, -1, -1, -1, 83, -1, 85, 23,
+ 24, 26, -1, 28, -1, -1, -1, 31, 32, 3,
+ -1, 35, -1, 37, 39, -1, 41, 42, -1, 13,
+ -1, -1, -1, 17, 49, -1, -1, 52, 53, -1,
+ -1, -1, 26, 58, 28, -1, -1, 31, -1, 64,
+ -1, -1, -1, -1, -1, 39, -1, 41, 42, -1,
+ -1, -1, -1, -1, 79, 49, -1, -1, 52, 53,
+ -1, -1, -1, -1, 58, -1, -1, 3, -1, -1,
+ 64, -1, -1, -1, -1, -1, -1, 13, -1, -1,
+ -1, 17, -1, -1, -1, 79, -1, -1, -1, -1,
+ 26, -1, 28, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 39, -1, 41, 42, -1, -1, -1,
+ -1, -1, -1, 49, -1, -1, 52, 53, -1, -1,
+ -1, -1, 58, -1, -1, -1, -1, -1, 64, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 79, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 12, 13, -1, -1, -1,
+ -1, -1, -1, -1, -1, 22, -1, -1, -1, -1,
+ -1, -1, 29, -1, -1, -1, 33, 34, -1, 36,
+ -1, -1, -1, -1, -1, -1, 43, -1, -1, -1,
+ 47, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 65, 66,
+ 67, -1, 69, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 80, 81, 82, -1, -1, -1, -1,
+ -1, -1, -1, -1, 11, 12, 13, -1, -1, -1,
+ -1, -1, -1, -1, -1, 22, -1, -1, -1, -1,
+ -1, -1, 29, -1, -1, -1, 33, 34, -1, 36,
+ -1, -1, -1, 40, -1, 42, 43, 44, -1, -1,
+ 47, -1, -1, -1, 51, -1, 53, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 65, 66,
+ 67, -1, 69, -1, 71, -1, 73, -1, 75, -1,
+ -1, -1, -1, 80, 81, 82, -1, -1, -1, -1,
+ -1, -1, -1, -1, 7, -1, -1, -1, 11, 12,
+ 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
+ -1, -1, -1, -1, -1, -1, 29, -1, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
+ 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
+ 53, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 65, 66, 67, -1, 69, -1, 71, -1,
+ 73, -1, 75, -1, -1, -1, -1, 80, 81, 82,
+ -1, -1, -1, -1, -1, -1, -1, -1, 11, 12,
+ 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
+ -1, -1, -1, -1, -1, -1, 29, -1, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
+ 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
+ 53, -1, -1, 56, -1, -1, -1, -1, -1, -1,
+ -1, -1, 65, 66, 67, -1, 69, -1, 71, -1,
+ 73, -1, 75, -1, -1, -1, -1, 80, 81, 82,
+ -1, -1, -1, -1, -1, -1, -1, -1, 11, 12,
+ 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
+ -1, -1, -1, -1, -1, -1, 29, -1, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
+ 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
+ 53, -1, -1, 56, -1, -1, -1, -1, -1, -1,
+ -1, -1, 65, 66, 67, -1, 69, -1, 71, -1,
+ 73, -1, 75, -1, -1, -1, -1, 80, 81, 82,
+ -1, -1, -1, -1, -1, -1, -1, -1, 11, 12,
+ 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
+ -1, -1, -1, -1, -1, -1, 29, -1, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
+ 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
+ 53, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 65, 66, 67, -1, 69, -1, 71, -1,
+ 73, 74, 75, -1, -1, -1, -1, 80, 81, 82,
+ -1, -1, -1, -1, -1, -1, -1, -1, 4, 5,
+ 6, -1, -1, 9, 10, 11, -1, -1, 14, -1,
+ 16, -1, -1, -1, 20, 21, 22, -1, -1, -1,
+ -1, -1, -1, 29, 30, 31, 32, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 43, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 59, -1, -1, -1, -1, -1, -1,
+ 66, 67, 68, 69, 70, -1, 72, 73, 74, 75,
+ 76, 77, -1, -1, 80, 81, 82, 83, 84, 85,
+ -1, -1, -1, -1, -1, 4, 5, 6, -1, -1,
+ 9, 10, 11, -1, -1, 14, -1, 16, -1, -1,
+ -1, 20, 21, 22, -1, -1, -1, -1, -1, -1,
+ 29, 30, 31, 32, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 43, -1, -1, -1, 47, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 59, -1, -1, -1, -1, -1, 65, 66, 67, 68,
+ 69, 70, -1, 72, 73, 74, 75, 76, 77, -1,
+ -1, 80, 81, 82, 83, 84, 85, -1, -1, -1,
+ -1, -1, 4, 5, 6, -1, -1, 9, 10, 11,
+ -1, -1, 14, -1, 16, -1, -1, -1, 20, 21,
+ 22, -1, -1, -1, -1, -1, -1, 29, 30, 31,
+ 32, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 43, -1, -1, -1, 47, -1, -1, -1, -1,
+ -1, -1, -1, 55, -1, -1, -1, 59, -1, -1,
+ -1, -1, -1, 65, 66, 67, 68, 69, 70, -1,
+ 72, 73, 74, 75, 76, 77, -1, -1, 80, 81,
+ 82, 83, 84, 85, -1, -1, -1, -1, -1, 4,
+ -1, -1, -1, -1, 9, -1, 11, 12, 13, 14,
+ -1, -1, -1, -1, -1, -1, 21, 22, -1, -1,
+ -1, -1, -1, -1, 29, 30, -1, -1, 33, 34,
+ -1, 36, -1, -1, -1, 40, -1, 42, 43, 44,
+ -1, -1, 47, -1, -1, -1, 51, -1, 53, -1,
+ -1, -1, -1, -1, 59, -1, 61, -1, -1, -1,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, -1, -1, 80, 81, 82, 83, 84,
+ -1, -1, -1, -1, -1, -1, 4, -1, -1, -1,
+ -1, 9, -1, 11, 12, 13, 14, -1, -1, -1,
+ -1, -1, -1, 21, 22, -1, -1, -1, -1, -1,
+ -1, 29, 30, -1, -1, 33, 34, -1, 36, -1,
+ -1, -1, 40, -1, 42, 43, 44, -1, -1, 47,
+ -1, -1, -1, 51, -1, 53, -1, -1, -1, -1,
+ -1, 59, -1, 61, -1, -1, -1, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ -1, -1, 80, 81, 82, 83, 84, -1, -1, -1,
+ -1, -1, -1, 4, -1, -1, -1, -1, 9, -1,
+ 11, 12, 13, 14, -1, -1, -1, -1, -1, -1,
+ 21, 22, -1, -1, -1, -1, -1, -1, 29, 30,
+ -1, -1, 33, 34, -1, 36, -1, -1, -1, 40,
+ -1, 42, 43, 44, -1, -1, 47, -1, -1, -1,
+ 51, -1, 53, -1, -1, -1, -1, -1, 59, -1,
+ 61, -1, -1, -1, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 77, -1, -1, 80,
+ 81, 82, 83, 84, -1, 86, -1, -1, -1, -1,
+ 4, 5, 6, -1, -1, 9, 10, 11, 12, 13,
+ 14, -1, 16, -1, -1, -1, 20, 21, 22, -1,
+ -1, -1, -1, -1, -1, 29, 30, 31, 32, 33,
+ 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
+ 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
+ -1, 55, -1, -1, -1, 59, -1, 61, -1, -1,
+ -1, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, -1, -1, 80, 81, 82, 83,
+ 84, 85, -1, -1, -1, -1, -1,
+
+ 77, 25, 25, 63, 94, 63, 16, 89, 19, 77,
+ 16, 16, 16, 59, 10, 14, 19, 19, 19, 14,
+ 5, 19, 6, 14, 6, 25, 19, 19, 25, 19,
+ 19, 25, 63, 21, 14, 16, 92, 16, 16, 14,
+ 16, 63, 25, 16, 16, 19, 15, -1, 25, 16,
+ 14, 16, 14, 19, 25, 25, 14, 16, 14, 19,
+ 14, -1, 19, 16, 19, 16, 14, 14, 36, 14,
+ 14, 39, 14, 16, 14, 27, 25, 16, 16, 25,
+ 16, -1, 19, -1, 16, -1, 36, 16, 19, 14,
+ 40, 14, -1, 19, -1, 36, -1, 30, 25, 40,
+ 33, 36, 36, 38, 19, 32, 36, 41, 36, -1,
+ 6, -1, 40, 28, 36, 36, 36, 36, 48, 41,
+ 41, -1, 60, 42, 60, 36, 46, 36, 60, -1,
+ 41, 60, 41, 36, 36, 38, 38, 36, 36, 38,
+ -1, 36, 36, 41, 81, 39, 41, 36, 36, 38,
+ 38, 36, 83, 38, 36, 36, 38, 38, 25, 36,
+ 36, 38, 38, 36, 36, 32, 38, 36, 41, 95,
+ 36, 96, 36, 42, 36, 36, 30, 41, 101, 33,
+ 41, 36, -1, 36, 50, 36, 41, 38, 41, 36,
+ 52, 38, 36, 36, -1, 36, -1, 36, 36, 42,
+ 44, 42, 41, 41, -1, 36, 36, 36, 36, 38,
+ 41, 41, 43, 41, 53, -1, -1, 36, 36, -1,
+ 58, 51, 41, 41, 43, 17, 18, 19, 36, 36,
+ 58, -1, -1, 41, 41, -1, 43, 36, 36, 47,
+ 58, 36, 41, 41, 43, 8, 41, 36, 36, -1,
+ 45, 49, 41, 41, 17, 18, 19, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 58,
+ 58, -1, -1, -1, 19, -1, -1, -1, -1, -1,
+ -1, -1, -1, 28, 29, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1};
+
diff --git a/src/declarative/qml/parser/javascriptgrammar_p.h b/src/declarative/qml/parser/javascriptgrammar_p.h
new file mode 100644
index 0000000..70c9766
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptgrammar_p.h
@@ -0,0 +1,200 @@
+// This file was generated by qlalr - DO NOT EDIT!
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef JAVASCRIPTGRAMMAR_P_H
+#define JAVASCRIPTGRAMMAR_P_H
+
+class JavaScriptGrammar
+{
+public:
+ enum {
+ EOF_SYMBOL = 0,
+ REDUCE_HERE = 90,
+ SHIFT_THERE = 89,
+ T_AND = 1,
+ T_AND_AND = 2,
+ T_AND_EQ = 3,
+ T_AUTOMATIC_SEMICOLON = 62,
+ T_BREAK = 4,
+ T_CASE = 5,
+ T_CATCH = 6,
+ T_COLON = 7,
+ T_COMMA = 8,
+ T_CONST = 83,
+ T_CONTINUE = 9,
+ T_DEBUGGER = 84,
+ T_DEFAULT = 10,
+ T_DELETE = 11,
+ T_DIVIDE_ = 12,
+ T_DIVIDE_EQ = 13,
+ T_DO = 14,
+ T_DOT = 15,
+ T_ELSE = 16,
+ T_EQ = 17,
+ T_EQ_EQ = 18,
+ T_EQ_EQ_EQ = 19,
+ T_FALSE = 82,
+ T_FINALLY = 20,
+ T_FOR = 21,
+ T_FUNCTION = 22,
+ T_GE = 23,
+ T_GT = 24,
+ T_GT_GT = 25,
+ T_GT_GT_EQ = 26,
+ T_GT_GT_GT = 27,
+ T_GT_GT_GT_EQ = 28,
+ T_IDENTIFIER = 29,
+ T_IF = 30,
+ T_IMPORT = 88,
+ T_IN = 31,
+ T_INSTANCEOF = 32,
+ T_LBRACE = 33,
+ T_LBRACKET = 34,
+ T_LE = 35,
+ T_LPAREN = 36,
+ T_LT = 37,
+ T_LT_LT = 38,
+ T_LT_LT_EQ = 39,
+ T_MINUS = 40,
+ T_MINUS_EQ = 41,
+ T_MINUS_MINUS = 42,
+ T_MULTILINE_STRING_LITERAL = 86,
+ T_NEW = 43,
+ T_NOT = 44,
+ T_NOT_EQ = 45,
+ T_NOT_EQ_EQ = 46,
+ T_NULL = 80,
+ T_NUMERIC_LITERAL = 47,
+ T_OR = 48,
+ T_OR_EQ = 49,
+ T_OR_OR = 50,
+ T_PLUS = 51,
+ T_PLUS_EQ = 52,
+ T_PLUS_PLUS = 53,
+ T_PROPERTY = 66,
+ T_PUBLIC = 87,
+ T_QUESTION = 54,
+ T_RBRACE = 55,
+ T_RBRACKET = 56,
+ T_REMAINDER = 57,
+ T_REMAINDER_EQ = 58,
+ T_RESERVED_WORD = 85,
+ T_RETURN = 59,
+ T_RPAREN = 60,
+ T_SEMICOLON = 61,
+ T_SIGNAL = 67,
+ T_STAR = 63,
+ T_STAR_EQ = 64,
+ T_STRING_LITERAL = 65,
+ T_SWITCH = 68,
+ T_THIS = 69,
+ T_THROW = 70,
+ T_TILDE = 71,
+ T_TRUE = 81,
+ T_TRY = 72,
+ T_TYPEOF = 73,
+ T_VAR = 74,
+ T_VOID = 75,
+ T_WHILE = 76,
+ T_WITH = 77,
+ T_XOR = 78,
+ T_XOR_EQ = 79,
+
+ ACCEPT_STATE = 552,
+ RULE_COUNT = 317,
+ STATE_COUNT = 553,
+ TERMINAL_COUNT = 91,
+ NON_TERMINAL_COUNT = 103,
+
+ GOTO_INDEX_OFFSET = 553,
+ GOTO_INFO_OFFSET = 1717,
+ GOTO_CHECK_OFFSET = 1717
+ };
+
+ static const char *const spell [];
+ static const int lhs [];
+ static const int rhs [];
+ static const int goto_default [];
+ static const int action_default [];
+ static const int action_index [];
+ static const int action_info [];
+ static const int action_check [];
+
+ static inline int nt_action (int state, int nt)
+ {
+ const int *const goto_index = &action_index [GOTO_INDEX_OFFSET];
+ const int *const goto_check = &action_check [GOTO_CHECK_OFFSET];
+
+ const int yyn = goto_index [state] + nt;
+
+ if (yyn < 0 || goto_check [yyn] != nt)
+ return goto_default [nt];
+
+ const int *const goto_info = &action_info [GOTO_INFO_OFFSET];
+ return goto_info [yyn];
+ }
+
+ static inline int t_action (int state, int token)
+ {
+ const int yyn = action_index [state] + token;
+
+ if (yyn < 0 || action_check [yyn] != token)
+ return - action_default [state];
+
+ return action_info [yyn];
+ }
+};
+
+
+#endif // JAVASCRIPTGRAMMAR_P_H
+
diff --git a/src/declarative/qml/parser/javascriptlexer.cpp b/src/declarative/qml/parser/javascriptlexer.cpp
new file mode 100644
index 0000000..c0a4b63
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptlexer.cpp
@@ -0,0 +1,1142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "javascriptengine_p.h"
+
+
+
+
+
+
+
+#include "javascriptlexer_p.h"
+#include "javascriptgrammar_p.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+extern double qstrtod(const char *s00, char const **se, bool *ok);
+
+#define shiftWindowsLineBreak() \
+ do { \
+ if (((current == '\r') && (next1 == '\n')) \
+ || ((current == '\n') && (next1 == '\r'))) { \
+ shift(1); \
+ } \
+ } \
+ while (0)
+
+namespace JavaScript {
+extern qjsreal integerFromString(const char *buf, int size, int radix);
+}
+
+JavaScript::Lexer::Lexer(JavaScriptEnginePrivate *eng)
+ : driver(eng),
+ yylineno(0),
+ done(false),
+ size8(128), size16(128),
+ pos8(0), pos16(0),
+ terminator(false),
+ restrKeyword(false),
+ delimited(false),
+ stackToken(-1),
+ state(Start),
+ pos(0),
+ code(0), length(0),
+ yycolumn(0),
+ startpos(0),
+ startlineno(0), startcolumn(0),
+ bol(true),
+ current(0), next1(0), next2(0), next3(0),
+ err(NoError),
+ wantRx(false),
+ check_reserved(true),
+ parenthesesState(IgnoreParentheses),
+ parenthesesCount(0),
+ prohibitAutomaticSemicolon(false)
+{
+ // allocate space for read buffers
+ buffer8 = new char[size8];
+ buffer16 = new QChar[size16];
+ pattern = 0;
+ flags = 0;
+
+}
+
+JavaScript::Lexer::~Lexer()
+{
+ delete [] buffer8;
+ delete [] buffer16;
+}
+
+void JavaScript::Lexer::setCode(const QString &c, int lineno)
+{
+ errmsg = QString();
+ yylineno = lineno;
+ yycolumn = 1;
+ restrKeyword = false;
+ delimited = false;
+ stackToken = -1;
+ pos = 0;
+ code = c.unicode();
+ length = c.length();
+ bol = true;
+
+ // read first characters
+ current = (length > 0) ? code[0].unicode() : 0;
+ next1 = (length > 1) ? code[1].unicode() : 0;
+ next2 = (length > 2) ? code[2].unicode() : 0;
+ next3 = (length > 3) ? code[3].unicode() : 0;
+}
+
+void JavaScript::Lexer::shift(uint p)
+{
+ while (p--) {
+ ++pos;
+ ++yycolumn;
+ current = next1;
+ next1 = next2;
+ next2 = next3;
+ next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
+ }
+}
+
+void JavaScript::Lexer::setDone(State s)
+{
+ state = s;
+ done = true;
+}
+
+int JavaScript::Lexer::findReservedWord(const QChar *c, int size) const
+{
+ switch (size) {
+ case 2: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o'))
+ return JavaScriptGrammar::T_DO;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f'))
+ return JavaScriptGrammar::T_IF;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n'))
+ return JavaScriptGrammar::T_IN;
+ } break;
+
+ case 3: {
+ if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r'))
+ return JavaScriptGrammar::T_FOR;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w'))
+ return JavaScriptGrammar::T_NEW;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y'))
+ return JavaScriptGrammar::T_TRY;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r'))
+ return JavaScriptGrammar::T_VAR;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 4: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_CASE;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_ELSE;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s'))
+ return JavaScriptGrammar::T_THIS;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d'))
+ return JavaScriptGrammar::T_VOID;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h'))
+ return JavaScriptGrammar::T_WITH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_TRUE;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l'))
+ return JavaScriptGrammar::T_NULL;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 5: {
+ if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('k'))
+ return JavaScriptGrammar::T_BREAK;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('h'))
+ return JavaScriptGrammar::T_CATCH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('w'))
+ return JavaScriptGrammar::T_THROW;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_WHILE;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_CONST;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_FALSE;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r')
+ && c[4] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('r'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('l'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('s'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 6: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_DELETE;
+ else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n'))
+ return JavaScriptGrammar::T_RETURN;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h'))
+ return JavaScriptGrammar::T_SWITCH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f'))
+ return JavaScriptGrammar::T_TYPEOF;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_IMPORT;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('g') && c[3] == QLatin1Char('n')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('l'))
+ return JavaScriptGrammar::T_SIGNAL;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b')
+ && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
+ return JavaScriptGrammar::T_PUBLIC;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i')
+ && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 7: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l')
+ && c[6] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_DEFAULT;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l')
+ && c[6] == QLatin1Char('y'))
+ return JavaScriptGrammar::T_FINALLY;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a')
+ && c[6] == QLatin1Char('n'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d')
+ && c[6] == QLatin1Char('s'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g')
+ && c[6] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t')
+ && c[6] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 8: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_CONTINUE;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n'))
+ return JavaScriptGrammar::T_FUNCTION;
+ else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u')
+ && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r'))
+ return JavaScriptGrammar::T_DEBUGGER;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('p')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('r')
+ && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('y'))
+ return JavaScriptGrammar::T_PROPERTY;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a')
+ && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 9: {
+ if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f')
+ && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c')
+ && c[8] == QLatin1Char('e'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n')
+ && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('t'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c')
+ && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e')
+ && c[8] == QLatin1Char('d'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 10: {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e')
+ && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f'))
+ return JavaScriptGrammar::T_INSTANCEOF;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 12: {
+ if (check_reserved) {
+ if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r')
+ && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z')
+ && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d'))
+ return JavaScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ } // switch
+
+ return -1;
+}
+
+int JavaScript::Lexer::lex()
+{
+ int token = 0;
+ state = Start;
+ ushort stringType = 0; // either single or double quotes
+ bool multiLineString = false;
+ pos8 = pos16 = 0;
+ done = false;
+ terminator = false;
+
+ // did we push a token on the stack previously ?
+ // (after an automatic semicolon insertion)
+ if (stackToken >= 0) {
+ setDone(Other);
+ token = stackToken;
+ stackToken = -1;
+ }
+
+ while (!done) {
+ switch (state) {
+ case Start:
+ if (isWhiteSpace()) {
+ // do nothing
+ } else if (current == '/' && next1 == '/') {
+ recordStartPos();
+ shift(1);
+ state = InSingleLineComment;
+ } else if (current == '/' && next1 == '*') {
+ recordStartPos();
+ shift(1);
+ state = InMultiLineComment;
+ } else if (current == 0) {
+ syncProhibitAutomaticSemicolon();
+ if (!terminator && !delimited && !prohibitAutomaticSemicolon) {
+ // automatic semicolon insertion if program incomplete
+ token = JavaScriptGrammar::T_SEMICOLON;
+ stackToken = 0;
+ setDone(Other);
+ } else {
+ setDone(Eof);
+ }
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ bol = true;
+ terminator = true;
+ syncProhibitAutomaticSemicolon();
+ if (restrKeyword) {
+ token = JavaScriptGrammar::T_SEMICOLON;
+ setDone(Other);
+ }
+ } else if (current == '"' || current == '\'') {
+ recordStartPos();
+ state = InString;
+ multiLineString = false;
+ stringType = current;
+ } else if (isIdentLetter(current)) {
+ recordStartPos();
+ record16(current);
+ state = InIdentifier;
+ } else if (current == '0') {
+ recordStartPos();
+ record8(current);
+ state = InNum0;
+ } else if (isDecimalDigit(current)) {
+ recordStartPos();
+ record8(current);
+ state = InNum;
+ } else if (current == '.' && isDecimalDigit(next1)) {
+ recordStartPos();
+ record8(current);
+ state = InDecimal;
+ } else {
+ recordStartPos();
+ token = matchPunctuator(current, next1, next2, next3);
+ if (token != -1) {
+ if (terminator && !delimited && !prohibitAutomaticSemicolon
+ && (token == JavaScriptGrammar::T_PLUS_PLUS
+ || token == JavaScriptGrammar::T_MINUS_MINUS)) {
+ // automatic semicolon insertion
+ stackToken = token;
+ token = JavaScriptGrammar::T_SEMICOLON;
+ }
+ setDone(Other);
+ }
+ else {
+ setDone(Bad);
+ err = IllegalCharacter;
+ errmsg = QLatin1String("Illegal character");
+ }
+ }
+ break;
+ case InString:
+ if (current == stringType) {
+ shift(1);
+ setDone(String);
+ } else if (isLineTerminator()) {
+ multiLineString = true;
+ record16(current);
+ } else if (current == 0 || isLineTerminator()) {
+ setDone(Bad);
+ err = UnclosedStringLiteral;
+ errmsg = QLatin1String("Unclosed string at end of line");
+ } else if (current == '\\') {
+ state = InEscapeSequence;
+ } else {
+ record16(current);
+ }
+ break;
+ // Escape Sequences inside of strings
+ case InEscapeSequence:
+ if (isOctalDigit(current)) {
+ if (current >= '0' && current <= '3' &&
+ isOctalDigit(next1) && isOctalDigit(next2)) {
+ record16(convertOctal(current, next1, next2));
+ shift(2);
+ state = InString;
+ } else if (isOctalDigit(current) &&
+ isOctalDigit(next1)) {
+ record16(convertOctal('0', current, next1));
+ shift(1);
+ state = InString;
+ } else if (isOctalDigit(current)) {
+ record16(convertOctal('0', '0', current));
+ state = InString;
+ } else {
+ setDone(Bad);
+ err = IllegalEscapeSequence;
+ errmsg = QLatin1String("Illegal escape squence");
+ }
+ } else if (current == 'x')
+ state = InHexEscape;
+ else if (current == 'u')
+ state = InUnicodeEscape;
+ else {
+ if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ bol = true;
+ } else {
+ record16(singleEscape(current));
+ }
+ state = InString;
+ }
+ break;
+ case InHexEscape:
+ if (isHexDigit(current) && isHexDigit(next1)) {
+ state = InString;
+ record16(QLatin1Char(convertHex(current, next1)));
+ shift(1);
+ } else if (current == stringType) {
+ record16(QLatin1Char('x'));
+ shift(1);
+ setDone(String);
+ } else {
+ record16(QLatin1Char('x'));
+ record16(current);
+ state = InString;
+ }
+ break;
+ case InUnicodeEscape:
+ if (isHexDigit(current) && isHexDigit(next1) &&
+ isHexDigit(next2) && isHexDigit(next3)) {
+ record16(convertUnicode(current, next1, next2, next3));
+ shift(3);
+ state = InString;
+ } else if (current == stringType) {
+ record16(QLatin1Char('u'));
+ shift(1);
+ setDone(String);
+ } else {
+ setDone(Bad);
+ err = IllegalUnicodeEscapeSequence;
+ errmsg = QLatin1String("Illegal unicode escape sequence");
+ }
+ break;
+ case InSingleLineComment:
+ if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ terminator = true;
+ bol = true;
+ if (restrKeyword) {
+ token = JavaScriptGrammar::T_SEMICOLON;
+ setDone(Other);
+ } else
+ state = Start;
+ } else if (current == 0) {
+ setDone(Eof);
+ }
+ break;
+ case InMultiLineComment:
+ if (current == 0) {
+ setDone(Bad);
+ err = UnclosedComment;
+ errmsg = QLatin1String("Unclosed comment at end of file");
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ } else if (current == '*' && next1 == '/') {
+ state = Start;
+ shift(1);
+ }
+ break;
+ case InIdentifier:
+ if (isIdentLetter(current) || isDecimalDigit(current)) {
+ record16(current);
+ break;
+ }
+ setDone(Identifier);
+ break;
+ case InNum0:
+ if (current == 'x' || current == 'X') {
+ record8(current);
+ state = InHex;
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else if (isOctalDigit(current)) {
+ record8(current);
+ state = InOctal;
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InHex:
+ if (isHexDigit(current))
+ record8(current);
+ else
+ setDone(Hex);
+ break;
+ case InOctal:
+ if (isOctalDigit(current)) {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Octal);
+ }
+ break;
+ case InNum:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InDecimal:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InExponentIndicator:
+ if (current == '+' || current == '-') {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InExponent;
+ } else {
+ setDone(Bad);
+ err = IllegalExponentIndicator;
+ errmsg = QLatin1String("Illegal syntax for exponential number");
+ }
+ break;
+ case InExponent:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else {
+ setDone(Number);
+ }
+ break;
+ default:
+ Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement");
+ }
+
+ // move on to the next character
+ if (!done)
+ shift(1);
+ if (state != Start && state != InSingleLineComment)
+ bol = false;
+ }
+
+ // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
+ if ((state == Number || state == Octal || state == Hex)
+ && isIdentLetter(current)) {
+ state = Bad;
+ err = IllegalIdentifier;
+ errmsg = QLatin1String("Identifier cannot start with numeric literal");
+ }
+
+ // terminate string
+ buffer8[pos8] = '\0';
+
+ double dval = 0;
+ if (state == Number) {
+ dval = qstrtod(buffer8, 0, 0);
+ } else if (state == Hex) { // scan hex numbers
+ dval = JavaScript::integerFromString(buffer8, pos8, 16);
+ state = Number;
+ } else if (state == Octal) { // scan octal number
+ dval = JavaScript::integerFromString(buffer8, pos8, 8);
+ state = Number;
+ }
+
+ restrKeyword = false;
+ delimited = false;
+
+ switch (parenthesesState) {
+ case IgnoreParentheses:
+ break;
+ case CountParentheses:
+ if (token == JavaScriptGrammar::T_RPAREN) {
+ --parenthesesCount;
+ if (parenthesesCount == 0)
+ parenthesesState = BalancedParentheses;
+ } else if (token == JavaScriptGrammar::T_LPAREN) {
+ ++parenthesesCount;
+ }
+ break;
+ case BalancedParentheses:
+ parenthesesState = IgnoreParentheses;
+ break;
+ }
+
+ switch (state) {
+ case Eof:
+ return 0;
+ case Other:
+ if (token == JavaScriptGrammar::T_RBRACE || token == JavaScriptGrammar::T_SEMICOLON)
+ delimited = true;
+ return token;
+ case Identifier:
+ if ((token = findReservedWord(buffer16, pos16)) < 0) {
+ /* TODO: close leak on parse error. same holds true for String */
+ if (driver)
+ qsyylval.ustr = driver->intern(buffer16, pos16);
+ else
+ qsyylval.ustr = 0;
+ return JavaScriptGrammar::T_IDENTIFIER;
+ }
+ if (token == JavaScriptGrammar::T_CONTINUE || token == JavaScriptGrammar::T_BREAK
+ || token == JavaScriptGrammar::T_RETURN || token == JavaScriptGrammar::T_THROW) {
+ restrKeyword = true;
+ } else if (token == JavaScriptGrammar::T_IF || token == JavaScriptGrammar::T_FOR
+ || token == JavaScriptGrammar::T_WHILE || token == JavaScriptGrammar::T_WITH) {
+ parenthesesState = CountParentheses;
+ parenthesesCount = 0;
+ } else if (token == JavaScriptGrammar::T_DO) {
+ parenthesesState = BalancedParentheses;
+ }
+ return token;
+ case String:
+ if (driver)
+ qsyylval.ustr = driver->intern(buffer16, pos16);
+ else
+ qsyylval.ustr = 0;
+ return multiLineString?JavaScriptGrammar::T_MULTILINE_STRING_LITERAL:JavaScriptGrammar::T_STRING_LITERAL;
+ case Number:
+ qsyylval.dval = dval;
+ return JavaScriptGrammar::T_NUMERIC_LITERAL;
+ case Bad:
+ return -1;
+ default:
+ Q_ASSERT(!"unhandled numeration value in switch");
+ return -1;
+ }
+}
+
+bool JavaScript::Lexer::isWhiteSpace() const
+{
+ return (current == ' ' || current == '\t' ||
+ current == 0x0b || current == 0x0c);
+}
+
+bool JavaScript::Lexer::isLineTerminator() const
+{
+ return (current == '\n' || current == '\r');
+}
+
+bool JavaScript::Lexer::isIdentLetter(ushort c)
+{
+ /* TODO: allow other legitimate unicode chars */
+ return ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || c == '$'
+ || c == '_');
+}
+
+bool JavaScript::Lexer::isDecimalDigit(ushort c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+bool JavaScript::Lexer::isHexDigit(ushort c) const
+{
+ return ((c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'f')
+ || (c >= 'A' && c <= 'F'));
+}
+
+bool JavaScript::Lexer::isOctalDigit(ushort c) const
+{
+ return (c >= '0' && c <= '7');
+}
+
+int JavaScript::Lexer::matchPunctuator(ushort c1, ushort c2,
+ ushort c3, ushort c4)
+{
+ if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
+ shift(4);
+ return JavaScriptGrammar::T_GT_GT_GT_EQ;
+ } else if (c1 == '=' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return JavaScriptGrammar::T_EQ_EQ_EQ;
+ } else if (c1 == '!' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return JavaScriptGrammar::T_NOT_EQ_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '>') {
+ shift(3);
+ return JavaScriptGrammar::T_GT_GT_GT;
+ } else if (c1 == '<' && c2 == '<' && c3 == '=') {
+ shift(3);
+ return JavaScriptGrammar::T_LT_LT_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '=') {
+ shift(3);
+ return JavaScriptGrammar::T_GT_GT_EQ;
+ } else if (c1 == '<' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_LE;
+ } else if (c1 == '>' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_GE;
+ } else if (c1 == '!' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_NOT_EQ;
+ } else if (c1 == '+' && c2 == '+') {
+ shift(2);
+ return JavaScriptGrammar::T_PLUS_PLUS;
+ } else if (c1 == '-' && c2 == '-') {
+ shift(2);
+ return JavaScriptGrammar::T_MINUS_MINUS;
+ } else if (c1 == '=' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_EQ_EQ;
+ } else if (c1 == '+' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_PLUS_EQ;
+ } else if (c1 == '-' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_MINUS_EQ;
+ } else if (c1 == '*' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_STAR_EQ;
+ } else if (c1 == '/' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_DIVIDE_EQ;
+ } else if (c1 == '&' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_AND_EQ;
+ } else if (c1 == '^' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_XOR_EQ;
+ } else if (c1 == '%' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_REMAINDER_EQ;
+ } else if (c1 == '|' && c2 == '=') {
+ shift(2);
+ return JavaScriptGrammar::T_OR_EQ;
+ } else if (c1 == '<' && c2 == '<') {
+ shift(2);
+ return JavaScriptGrammar::T_LT_LT;
+ } else if (c1 == '>' && c2 == '>') {
+ shift(2);
+ return JavaScriptGrammar::T_GT_GT;
+ } else if (c1 == '&' && c2 == '&') {
+ shift(2);
+ return JavaScriptGrammar::T_AND_AND;
+ } else if (c1 == '|' && c2 == '|') {
+ shift(2);
+ return JavaScriptGrammar::T_OR_OR;
+ }
+
+ switch(c1) {
+ case '=': shift(1); return JavaScriptGrammar::T_EQ;
+ case '>': shift(1); return JavaScriptGrammar::T_GT;
+ case '<': shift(1); return JavaScriptGrammar::T_LT;
+ case ',': shift(1); return JavaScriptGrammar::T_COMMA;
+ case '!': shift(1); return JavaScriptGrammar::T_NOT;
+ case '~': shift(1); return JavaScriptGrammar::T_TILDE;
+ case '?': shift(1); return JavaScriptGrammar::T_QUESTION;
+ case ':': shift(1); return JavaScriptGrammar::T_COLON;
+ case '.': shift(1); return JavaScriptGrammar::T_DOT;
+ case '+': shift(1); return JavaScriptGrammar::T_PLUS;
+ case '-': shift(1); return JavaScriptGrammar::T_MINUS;
+ case '*': shift(1); return JavaScriptGrammar::T_STAR;
+ case '/': shift(1); return JavaScriptGrammar::T_DIVIDE_;
+ case '&': shift(1); return JavaScriptGrammar::T_AND;
+ case '|': shift(1); return JavaScriptGrammar::T_OR;
+ case '^': shift(1); return JavaScriptGrammar::T_XOR;
+ case '%': shift(1); return JavaScriptGrammar::T_REMAINDER;
+ case '(': shift(1); return JavaScriptGrammar::T_LPAREN;
+ case ')': shift(1); return JavaScriptGrammar::T_RPAREN;
+ case '{': shift(1); return JavaScriptGrammar::T_LBRACE;
+ case '}': shift(1); return JavaScriptGrammar::T_RBRACE;
+ case '[': shift(1); return JavaScriptGrammar::T_LBRACKET;
+ case ']': shift(1); return JavaScriptGrammar::T_RBRACKET;
+ case ';': shift(1); return JavaScriptGrammar::T_SEMICOLON;
+
+ default: return -1;
+ }
+}
+
+ushort JavaScript::Lexer::singleEscape(ushort c) const
+{
+ switch(c) {
+ case 'b':
+ return 0x08;
+ case 't':
+ return 0x09;
+ case 'n':
+ return 0x0A;
+ case 'v':
+ return 0x0B;
+ case 'f':
+ return 0x0C;
+ case 'r':
+ return 0x0D;
+ case '"':
+ return 0x22;
+ case '\'':
+ return 0x27;
+ case '\\':
+ return 0x5C;
+ default:
+ return c;
+ }
+}
+
+ushort JavaScript::Lexer::convertOctal(ushort c1, ushort c2,
+ ushort c3) const
+{
+ return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
+}
+
+unsigned char JavaScript::Lexer::convertHex(ushort c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else
+ return (c - 'A' + 10);
+}
+
+unsigned char JavaScript::Lexer::convertHex(ushort c1, ushort c2)
+{
+ return ((convertHex(c1) << 4) + convertHex(c2));
+}
+
+QChar JavaScript::Lexer::convertUnicode(ushort c1, ushort c2,
+ ushort c3, ushort c4)
+{
+ return QChar((convertHex(c3) << 4) + convertHex(c4),
+ (convertHex(c1) << 4) + convertHex(c2));
+}
+
+void JavaScript::Lexer::record8(ushort c)
+{
+ Q_ASSERT(c <= 0xff);
+
+ // enlarge buffer if full
+ if (pos8 >= size8 - 1) {
+ char *tmp = new char[2 * size8];
+ memcpy(tmp, buffer8, size8 * sizeof(char));
+ delete [] buffer8;
+ buffer8 = tmp;
+ size8 *= 2;
+ }
+
+ buffer8[pos8++] = (char) c;
+}
+
+void JavaScript::Lexer::record16(QChar c)
+{
+ // enlarge buffer if full
+ if (pos16 >= size16 - 1) {
+ QChar *tmp = new QChar[2 * size16];
+ memcpy(tmp, buffer16, size16 * sizeof(QChar));
+ delete [] buffer16;
+ buffer16 = tmp;
+ size16 *= 2;
+ }
+
+ buffer16[pos16++] = c;
+}
+
+void JavaScript::Lexer::recordStartPos()
+{
+ startpos = pos;
+ startlineno = yylineno;
+ startcolumn = yycolumn;
+}
+
+bool JavaScript::Lexer::scanRegExp(RegExpBodyPrefix prefix)
+{
+ pos16 = 0;
+ bool lastWasEscape = false;
+
+ if (prefix == EqualPrefix)
+ record16(QLatin1Char('='));
+
+ while (1) {
+ if (isLineTerminator() || current == 0) {
+ errmsg = QLatin1String("Unterminated regular expression literal");
+ return false;
+ }
+ else if (current != '/' || lastWasEscape == true)
+ {
+ record16(current);
+ lastWasEscape = !lastWasEscape && (current == '\\');
+ }
+ else {
+ if (driver)
+ pattern = driver->intern(buffer16, pos16);
+ else
+ pattern = 0;
+ pos16 = 0;
+ shift(1);
+ break;
+ }
+ shift(1);
+ }
+
+ flags = 0;
+ while (isIdentLetter(current)) {
+ int flag = JavaScript::Ecma::RegExp::flagFromChar(current);
+ if (flag == 0) {
+ errmsg = QString::fromLatin1("Invalid regular expression flag '%0'")
+ .arg(QChar(current));
+ return false;
+ }
+ flags |= flag;
+ record16(current);
+ shift(1);
+ }
+
+ return true;
+}
+
+void JavaScript::Lexer::syncProhibitAutomaticSemicolon()
+{
+ if (parenthesesState == BalancedParentheses) {
+ // we have seen something like "if (foo)", which means we should
+ // never insert an automatic semicolon at this point, since it would
+ // then be expanded into an empty statement (ECMA-262 7.9.1)
+ prohibitAutomaticSemicolon = true;
+ parenthesesState = IgnoreParentheses;
+ } else {
+ prohibitAutomaticSemicolon = false;
+ }
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/javascriptlexer_p.h b/src/declarative/qml/parser/javascriptlexer_p.h
new file mode 100644
index 0000000..e71c10c
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptlexer_p.h
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTLEXER_P_H
+#define JAVASCRIPTLEXER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QString>
+
+
+
+QT_BEGIN_NAMESPACE
+
+class JavaScriptEnginePrivate;
+class JavaScriptNameIdImpl;
+
+namespace JavaScript {
+
+class Lexer
+{
+public:
+ Lexer(JavaScriptEnginePrivate *eng);
+ ~Lexer();
+
+ void setCode(const QString &c, int lineno);
+ int lex();
+
+ int currentLineNo() const { return yylineno; }
+ int currentColumnNo() const { return yycolumn; }
+
+ int tokenOffset() const { return startpos; }
+ int tokenLength() const { return pos - startpos; }
+
+ int startLineNo() const { return startlineno; }
+ int startColumnNo() const { return startcolumn; }
+
+ int endLineNo() const { return currentLineNo(); }
+ int endColumnNo() const
+ { int col = currentColumnNo(); return (col > 0) ? col - 1 : col; }
+
+ bool prevTerminator() const { return terminator; }
+
+ enum State { Start,
+ Identifier,
+ InIdentifier,
+ InSingleLineComment,
+ InMultiLineComment,
+ InNum,
+ InNum0,
+ InHex,
+ InOctal,
+ InDecimal,
+ InExponentIndicator,
+ InExponent,
+ Hex,
+ Octal,
+ Number,
+ String,
+ Eof,
+ InString,
+ InEscapeSequence,
+ InHexEscape,
+ InUnicodeEscape,
+ Other,
+ Bad };
+
+ enum Error {
+ NoError,
+ IllegalCharacter,
+ UnclosedStringLiteral,
+ IllegalEscapeSequence,
+ IllegalUnicodeEscapeSequence,
+ UnclosedComment,
+ IllegalExponentIndicator,
+ IllegalIdentifier
+ };
+
+ enum ParenthesesState {
+ IgnoreParentheses,
+ CountParentheses,
+ BalancedParentheses
+ };
+
+ enum RegExpBodyPrefix {
+ NoPrefix,
+ EqualPrefix
+ };
+
+ bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix);
+
+ JavaScriptNameIdImpl *pattern;
+ int flags;
+
+ State lexerState() const
+ { return state; }
+
+ QString errorMessage() const
+ { return errmsg; }
+ void setErrorMessage(const QString &err)
+ { errmsg = err; }
+ void setErrorMessage(const char *err)
+ { setErrorMessage(QString::fromLatin1(err)); }
+
+ Error error() const
+ { return err; }
+ void clearError()
+ { err = NoError; }
+
+private:
+ JavaScriptEnginePrivate *driver;
+ int yylineno;
+ bool done;
+ char *buffer8;
+ QChar *buffer16;
+ uint size8, size16;
+ uint pos8, pos16;
+ bool terminator;
+ bool restrKeyword;
+ // encountered delimiter like "'" and "}" on last run
+ bool delimited;
+ int stackToken;
+
+ State state;
+ void setDone(State s);
+ uint pos;
+ void shift(uint p);
+ int lookupKeyword(const char *);
+
+ bool isWhiteSpace() const;
+ bool isLineTerminator() const;
+ bool isHexDigit(ushort c) const;
+ bool isOctalDigit(ushort c) const;
+
+ int matchPunctuator(ushort c1, ushort c2,
+ ushort c3, ushort c4);
+ ushort singleEscape(ushort c) const;
+ ushort convertOctal(ushort c1, ushort c2,
+ ushort c3) const;
+public:
+ static unsigned char convertHex(ushort c1);
+ static unsigned char convertHex(ushort c1, ushort c2);
+ static QChar convertUnicode(ushort c1, ushort c2,
+ ushort c3, ushort c4);
+ static bool isIdentLetter(ushort c);
+ static bool isDecimalDigit(ushort c);
+
+ inline int ival() const { return qsyylval.ival; }
+ inline double dval() const { return qsyylval.dval; }
+ inline JavaScriptNameIdImpl *ustr() const { return qsyylval.ustr; }
+
+ const QChar *characterBuffer() const { return buffer16; }
+ int characterCount() const { return pos16; }
+
+private:
+ void record8(ushort c);
+ void record16(QChar c);
+ void recordStartPos();
+
+ int findReservedWord(const QChar *buffer, int size) const;
+
+ void syncProhibitAutomaticSemicolon();
+
+ const QChar *code;
+ uint length;
+ int yycolumn;
+ int startpos;
+ int startlineno;
+ int startcolumn;
+ int bol; // begin of line
+
+ union {
+ int ival;
+ double dval;
+ JavaScriptNameIdImpl *ustr;
+ } qsyylval;
+
+ // current and following unicode characters
+ ushort current, next1, next2, next3;
+
+ struct keyword {
+ const char *name;
+ int token;
+ };
+
+ QString errmsg;
+ Error err;
+
+ bool wantRx;
+ bool check_reserved;
+
+ ParenthesesState parenthesesState;
+ int parenthesesCount;
+ bool prohibitAutomaticSemicolon;
+};
+
+} // namespace JavaScript
+
+QT_END_NAMESPACE
+
+
+
+#endif
diff --git a/src/declarative/qml/parser/javascriptmemorypool_p.h b/src/declarative/qml/parser/javascriptmemorypool_p.h
new file mode 100644
index 0000000..cff7677
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptmemorypool_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTMEMORYPOOL_P_H
+#define JAVASCRIPTMEMORYPOOL_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/qglobal.h>
+#include <QtCore/qshareddata.h>
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript {
+
+class MemoryPool : public QSharedData
+{
+public:
+ enum { maxBlockCount = -1 };
+ enum { defaultBlockSize = 1 << 12 };
+
+ MemoryPool() {
+ m_blockIndex = maxBlockCount;
+ m_currentIndex = 0;
+ m_storage = 0;
+ m_currentBlock = 0;
+ m_currentBlockSize = 0;
+ }
+
+ virtual ~MemoryPool() {
+ for (int index = 0; index < m_blockIndex + 1; ++index)
+ qFree(m_storage[index]);
+
+ qFree(m_storage);
+ }
+
+ char *allocate(int bytes) {
+ bytes += (8 - bytes) & 7; // ensure multiple of 8 bytes (maintain alignment)
+ if (m_currentBlock == 0 || m_currentBlockSize < m_currentIndex + bytes) {
+ ++m_blockIndex;
+ m_currentBlockSize = defaultBlockSize << m_blockIndex;
+
+ m_storage = reinterpret_cast<char**>(qRealloc(m_storage, sizeof(char*) * (1 + m_blockIndex)));
+ m_currentBlock = m_storage[m_blockIndex] = reinterpret_cast<char*>(qMalloc(m_currentBlockSize));
+ ::memset(m_currentBlock, 0, m_currentBlockSize);
+
+ m_currentIndex = (8 - quintptr(m_currentBlock)) & 7; // ensure first chunk is 64-bit aligned
+ Q_ASSERT(m_currentIndex + bytes <= m_currentBlockSize);
+ }
+
+ char *p = reinterpret_cast<char *>
+ (m_currentBlock + m_currentIndex);
+
+ m_currentIndex += bytes;
+
+ return p;
+ }
+
+ int bytesAllocated() const {
+ int bytes = 0;
+ for (int index = 0; index < m_blockIndex; ++index)
+ bytes += (defaultBlockSize << index);
+ bytes += m_currentIndex;
+ return bytes;
+ }
+
+private:
+ int m_blockIndex;
+ int m_currentIndex;
+ char *m_currentBlock;
+ int m_currentBlockSize;
+ char **m_storage;
+
+private:
+ Q_DISABLE_COPY(MemoryPool)
+};
+
+} // namespace JavaScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/javascriptnodepool_p.h b/src/declarative/qml/parser/javascriptnodepool_p.h
new file mode 100644
index 0000000..3f59123
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptnodepool_p.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTNODEPOOL_P_H
+#define JAVASCRIPTNODEPOOL_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/QHash>
+#include <QtCore/QString>
+
+#include "javascriptmemorypool_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class JavaScriptEnginePrivate;
+
+namespace JavaScript {
+
+namespace AST {
+class Node;
+} // namespace AST
+
+class Code;
+class CompilationUnit;
+
+template <typename NodeType>
+inline NodeType *makeAstNode(MemoryPool *storage)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType();
+ return node;
+}
+
+template <typename NodeType, typename Arg1>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1);
+ return node;
+}
+
+template <typename NodeType, typename Arg1, typename Arg2>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2);
+ return node;
+}
+
+template <typename NodeType, typename Arg1, typename Arg2, typename Arg3>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3);
+ return node;
+}
+
+template <typename NodeType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3, arg4);
+ return node;
+}
+
+class NodePool : public MemoryPool
+{
+public:
+ NodePool(const QString &fileName, JavaScriptEnginePrivate *engine);
+ virtual ~NodePool();
+
+ Code *createCompiledCode(AST::Node *node, CompilationUnit &compilation);
+
+ inline QString fileName() const { return m_fileName; }
+ inline JavaScriptEnginePrivate *engine() const { return m_engine; }
+#ifndef J_SCRIPT_NO_EVENT_NOTIFY
+ inline qint64 id() const { return m_id; }
+#endif
+
+private:
+ QHash<AST::Node*, Code*> m_codeCache;
+ QString m_fileName;
+ JavaScriptEnginePrivate *m_engine;
+#ifndef J_SCRIPT_NO_EVENT_NOTIFY
+ qint64 m_id;
+#endif
+
+private:
+ Q_DISABLE_COPY(NodePool)
+};
+
+} // namespace JavaScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/javascriptparser.cpp b/src/declarative/qml/parser/javascriptparser.cpp
new file mode 100644
index 0000000..ed791c8
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptparser.cpp
@@ -0,0 +1,1658 @@
+// This file was generated by qlalr - DO NOT EDIT!
+
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtDebug>
+
+#include <string.h>
+
+#include "javascriptengine_p.h"
+#include "javascriptlexer_p.h"
+#include "javascriptast_p.h"
+#include "javascriptnodepool_p.h"
+
+
+
+#include "javascriptparser_p.h"
+
+//
+// This file is automatically generated from javascript.g.
+// Changes will be lost.
+//
+
+using namespace JavaScript;
+
+QT_BEGIN_NAMESPACE
+
+void JavaScriptParser::reallocateStack()
+{
+ if (! stack_size)
+ stack_size = 128;
+ else
+ stack_size <<= 1;
+
+ sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
+ state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+ location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation)));
+}
+
+inline static bool automatic(JavaScriptEnginePrivate *driver, int token)
+{
+ return token == JavaScriptGrammar::T_RBRACE
+ || token == 0
+ || driver->lexer()->prevTerminator();
+}
+
+
+JavaScriptParser::JavaScriptParser():
+ tos(0),
+ stack_size(0),
+ sym_stack(0),
+ state_stack(0),
+ location_stack(0),
+ first_token(0),
+ last_token(0)
+{
+}
+
+JavaScriptParser::~JavaScriptParser()
+{
+ if (stack_size) {
+ qFree(sym_stack);
+ qFree(state_stack);
+ qFree(location_stack);
+ }
+}
+
+static inline AST::SourceLocation location(Lexer *lexer)
+{
+ AST::SourceLocation loc;
+ loc.offset = lexer->tokenOffset();
+ loc.length = lexer->tokenLength();
+ loc.startLine = lexer->startLineNo();
+ loc.startColumn = lexer->startColumnNo();
+ return loc;
+}
+
+bool JavaScriptParser::parse(JavaScriptEnginePrivate *driver)
+{
+ Lexer *lexer = driver->lexer();
+ bool hadErrors = false;
+ int yytoken = -1;
+ int action = 0;
+
+ first_token = last_token = 0;
+
+ tos = -1;
+ program = 0;
+
+ do {
+ if (++tos == stack_size)
+ reallocateStack();
+
+ state_stack[tos] = action;
+
+ _Lcheck_token:
+ if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
+ yyprevlloc = yylloc;
+
+ if (first_token == last_token) {
+ yytoken = lexer->lex();
+ yylval = lexer->dval();
+ yylloc = location(lexer);
+ } else {
+ yytoken = first_token->token;
+ yylval = first_token->dval;
+ yylloc = first_token->loc;
+ ++first_token;
+ }
+ }
+
+ action = t_action(action, yytoken);
+ if (action > 0) {
+ if (action != ACCEPT_STATE) {
+ yytoken = -1;
+ sym(1).dval = yylval;
+ loc(1) = yylloc;
+ } else {
+ --tos;
+ return ! hadErrors;
+ }
+ } else if (action < 0) {
+ const int r = -action - 1;
+ tos -= rhs[r];
+
+ switch (r) {
+
+case 0: {
+ program = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList,
+ sym(2).UiObjectMemberList->finish());
+ sym(1).UiProgram = program;
+} break;
+
+case 2: {
+ sym(1).Node = sym(1).UiImportList->finish();
+} break;
+
+case 3: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport);
+} break;
+
+case 4: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(),
+ sym(1).UiImportList, sym(2).UiImport);
+} break;
+
+case 6: {
+ AST::UiImport *node = makeAstNode<AST::UiImport>(driver->nodePool(), sym(2).sval);
+ node->importToken = loc(1);
+ node->fileNameToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 7: {
+ sym(1).Node = 0;
+} break;
+
+case 8: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 9: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 10: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(2).UiObjectMember);
+ sym(1).Node = node;
+} break;
+
+case 11: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 12: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(3).UiObjectMember);
+ sym(1).Node = node;
+} break;
+
+case 13: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 14: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish());
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 15: {
+ AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(),
+ sym(3).sval, sym(4).UiObjectInitializer);
+ node->colonToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 16: {
+ AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).sval,
+ sym(2).UiObjectInitializer);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 18: {
+ AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(),
+ sym(4).UiObjectMemberList->finish());
+ node->colonToken = loc(2);
+ node->lbracketToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 19: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 21: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+ case 22:
+case 23: {
+ AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(), sym(1).UiQualifiedId->finish(),
+ sym(3).Statement);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 24:
+
+case 25: {
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+ break;
+}
+
+case 27: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (JavaScriptNameIdImpl *)0, sym(2).sval);
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 29: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->semicolonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 31: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->semicolonToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 33: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval,
+ sym(5).Expression);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->colonToken = loc(4);
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+
+case 35: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 36: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+
+case 37: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+case 38:
+case 39:
+{
+ AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 41: {
+ QString s = QLatin1String(JavaScriptGrammar::spell[T_PROPERTY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 42: {
+ QString s = QLatin1String(JavaScriptGrammar::spell[T_SIGNAL]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 43: {
+ AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 44: {
+ AST::UiQualifiedId *node = makeAstNode<AST::UiQualifiedId> (driver->nodePool(), sym(1).UiQualifiedId, sym(3).sval);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 45: {
+ AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool());
+ node->thisToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 46: {
+ AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 47: {
+ AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool());
+ node->nullToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 48: {
+ AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool());
+ node->trueToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 49: {
+ AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool());
+ node->falseToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 50: {
+ AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 51: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 52: {
+ bool rx = lexer->scanRegExp(Lexer::NoPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false; // ### remove me
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 53: {
+ bool rx = lexer->scanRegExp(Lexer::EqualPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false;
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 54: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision);
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 55: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 56: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), sym(4).Elision);
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 57: {
+ AST::ObjectLiteral *node = 0;
+ if (sym(2).Node)
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ else
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 58: {
+ AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 59: {
+ AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression);
+ node->lparenToken = loc(1);
+ node->rparenToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 60: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision, sym(2).Expression);
+} break;
+
+case 61: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision, sym(4).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 62: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool());
+ node->commaToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 63: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 64: {
+ sym(1).Node = 0;
+} break;
+
+case 65: {
+ sym(1).Elision = sym(1).Elision->finish ();
+} break;
+
+case 66: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyName, sym(3).Expression);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 67: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression);
+ node->commaToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 68: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+case 69:
+case 70: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 71: {
+ AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 72: {
+ AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 73: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 74:
+
+case 75:
+
+case 76:
+
+case 77:
+
+case 78:
+
+case 79:
+
+case 80:
+
+case 81:
+
+case 82:
+
+case 83:
+
+case 84:
+
+case 85:
+
+case 86:
+
+case 87:
+
+case 88:
+
+case 89:
+
+case 90:
+
+case 91:
+
+case 92:
+
+case 93:
+
+case 94:
+
+case 95:
+
+case 96:
+
+case 97:
+
+case 98:
+
+case 99:
+
+case 100:
+
+case 101:
+
+case 102:
+
+case 103:
+
+case 104:
+{
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+} break;
+
+case 109: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 110: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 111: {
+ AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList);
+ node->newToken = loc(1);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 113: {
+ AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression);
+ node->newToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 114: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 115: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 116: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 117: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 118: {
+ sym(1).Node = 0;
+} break;
+
+case 119: {
+ sym(1).Node = sym(1).ArgumentList->finish();
+} break;
+
+case 120: {
+ sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression);
+} break;
+
+case 121: {
+ AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 125: {
+ AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->incrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 126: {
+ AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->decrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 128: {
+ AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression);
+ node->deleteToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 129: {
+ AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression);
+ node->voidToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 130: {
+ AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression);
+ node->typeofToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 131: {
+ AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->incrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 132: {
+ AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->decrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 133: {
+ AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression);
+ node->plusToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 134: {
+ AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression);
+ node->minusToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 135: {
+ AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression);
+ node->tildeToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 136: {
+ AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression);
+ node->notToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 138: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mul, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 139: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Div, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 140: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mod, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 142: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Add, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 143: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Sub, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 145: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::LShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 146: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::RShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 147: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::URShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 149: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 150: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 151: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 152: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 153: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 154: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::In, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 156: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 157: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 158: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 159: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 160: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 162: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 163: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 164: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 165: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 167: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 168: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 169: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 170: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 172: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 174: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 176: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 178: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 180: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 182: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 184: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 186: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 188: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 190: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 192: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 194: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 196: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 198: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 199: {
+ sym(1).ival = QSOperator::Assign;
+} break;
+
+case 200: {
+ sym(1).ival = QSOperator::InplaceMul;
+} break;
+
+case 201: {
+ sym(1).ival = QSOperator::InplaceDiv;
+} break;
+
+case 202: {
+ sym(1).ival = QSOperator::InplaceMod;
+} break;
+
+case 203: {
+ sym(1).ival = QSOperator::InplaceAdd;
+} break;
+
+case 204: {
+ sym(1).ival = QSOperator::InplaceSub;
+} break;
+
+case 205: {
+ sym(1).ival = QSOperator::InplaceLeftShift;
+} break;
+
+case 206: {
+ sym(1).ival = QSOperator::InplaceRightShift;
+} break;
+
+case 207: {
+ sym(1).ival = QSOperator::InplaceURightShift;
+} break;
+
+case 208: {
+ sym(1).ival = QSOperator::InplaceAnd;
+} break;
+
+case 209: {
+ sym(1).ival = QSOperator::InplaceXor;
+} break;
+
+case 210: {
+ sym(1).ival = QSOperator::InplaceOr;
+} break;
+
+case 212: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 213: {
+ sym(1).Node = 0;
+} break;
+
+case 216: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 217: {
+ sym(1).Node = 0;
+} break;
+
+case 234: {
+ AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 235: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement);
+} break;
+
+case 236: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement);
+} break;
+
+case 237: {
+ sym(1).Node = 0;
+} break;
+
+case 238: {
+ sym(1).Node = sym(1).StatementList->finish ();
+} break;
+
+case 240: {
+ AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(),
+ sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST));
+ node->declarationKindToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 241: {
+ sym(1).ival = T_CONST;
+} break;
+
+case 242: {
+ sym(1).ival = T_VAR;
+} break;
+
+case 243: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+
+case 244: {
+ AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(),
+ sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 245: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+
+case 246: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+} break;
+
+case 247: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 248: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 249: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+
+case 250: {
+ sym(1).Node = 0;
+} break;
+
+case 252: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+
+case 253: {
+ sym(1).Node = 0;
+} break;
+
+case 255: {
+ AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool());
+ node->semicolonToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 257: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 258: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->elseToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 259: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 261: {
+ AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression);
+ node->doToken = loc(1);
+ node->whileToken = loc(3);
+ node->lparenToken = loc(4);
+ node->rparenToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 262: {
+ AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->whileToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 263: {
+ AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Expression, sym(9).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->firstSemicolonToken = loc(4);
+ node->secondSemicolonToken = loc(6);
+ node->rparenToken = loc(8);
+ sym(1).Node = node;
+} break;
+
+case 264: {
+ AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(),
+ sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression,
+ sym(8).Expression, sym(10).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->firstSemicolonToken = loc(5);
+ node->secondSemicolonToken = loc(7);
+ node->rparenToken = loc(9);
+ sym(1).Node = node;
+} break;
+
+case 265: {
+ AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->inToken = loc(4);
+ node->rparenToken = loc(6);
+ sym(1).Node = node;
+} break;
+
+case 266: {
+ AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(),
+ sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->inToken = loc(5);
+ node->rparenToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 268: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool());
+ node->continueToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 270: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval);
+ node->continueToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 272: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool());
+ node->breakToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 274: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval);
+ node->breakToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 276: {
+ AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression);
+ node->returnToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 277: {
+ AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->withToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 278: {
+ AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock);
+ node->switchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 279: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 280: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 281: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause);
+} break;
+
+case 282: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause);
+} break;
+
+case 283: {
+ sym(1).Node = 0;
+} break;
+
+case 284: {
+ sym(1).Node = sym(1).CaseClauses->finish ();
+} break;
+
+case 285: {
+ AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList);
+ node->caseToken = loc(1);
+ node->colonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 286: {
+ AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList);
+ node->defaultToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+case 287:
+case 288: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 289: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 291: {
+ AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression);
+ node->throwToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 292: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 293: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 294: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 295: {
+ AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block);
+ node->catchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->identifierToken = loc(3);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 296: {
+ AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block);
+ node->finallyToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 298: {
+ AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool());
+ node->debuggerToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 299: {
+ AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+
+case 300: {
+ AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ if (sym(2).sval)
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+
+case 301: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 302: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 303: {
+ sym(1).Node = 0;
+} break;
+
+case 304: {
+ sym(1).Node = sym(1).FormalParameterList->finish ();
+} break;
+
+case 305: {
+ sym(1).Node = 0;
+} break;
+
+case 307: {
+ sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ());
+} break;
+
+case 308: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement);
+} break;
+
+case 309: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement);
+} break;
+
+case 310: {
+ sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement);
+} break;
+
+case 311: {
+ sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration);
+} break;
+
+case 312: {
+ sym(1).sval = 0;
+} break;
+
+case 314: {
+ sym(1).Node = 0;
+} break;
+
+ } // switch
+ action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT);
+ } // if
+ } while (action != 0);
+
+ if (first_token == last_token) {
+ const int errorState = state_stack[tos];
+
+ // automatic insertion of `;'
+ if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) {
+ SavedToken &tk = token_buffer[0];
+ tk.token = yytoken;
+ tk.dval = yylval;
+ tk.loc = yylloc;
+
+ yylloc = yyprevlloc;
+ yylloc.offset += yylloc.length;
+ yylloc.startColumn += yylloc.length;
+ yylloc.length = 0;
+
+ //const QString msg = QString::fromUtf8("Missing `;'");
+ //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg));
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ yytoken = T_SEMICOLON;
+ yylval = 0;
+
+ action = errorState;
+
+ goto _Lcheck_token;
+ }
+
+ hadErrors = true;
+
+ token_buffer[0].token = yytoken;
+ token_buffer[0].dval = yylval;
+ token_buffer[0].loc = yylloc;
+
+ token_buffer[1].token = yytoken = lexer->lex();
+ token_buffer[1].dval = yylval = lexer->dval();
+ token_buffer[1].loc = yylloc = location(lexer);
+
+ if (t_action(errorState, yytoken)) {
+ const QString msg = QString::fromUtf8("Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+
+ static int tokens[] = {
+ T_PLUS,
+ T_EQ,
+
+ T_COMMA,
+ T_COLON,
+ T_SEMICOLON,
+
+ T_RPAREN, T_RBRACKET, T_RBRACE,
+
+ T_NUMERIC_LITERAL,
+ T_IDENTIFIER,
+
+ T_LPAREN, T_LBRACKET, T_LBRACE,
+
+ EOF_SYMBOL
+ };
+
+ for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
+ int a = t_action(errorState, *tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[*tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = *tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[2];
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ for (int tk = 1; tk < TERMINAL_COUNT; ++tk) {
+ if (tk == T_AUTOMATIC_SEMICOLON)
+ continue;
+
+ int a = t_action(errorState, tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ const QString msg = QString::fromUtf8("Syntax error");
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/javascriptparser_p.h b/src/declarative/qml/parser/javascriptparser_p.h
new file mode 100644
index 0000000..5e68fe7
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptparser_p.h
@@ -0,0 +1,216 @@
+// This file was generated by qlalr - DO NOT EDIT!
+
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// 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.
+//
+
+//
+// This file is automatically generated from javascript.g.
+// Changes will be lost.
+//
+
+#ifndef JAVASCRIPTPARSER_P_H
+#define JAVASCRIPTPARSER_P_H
+
+#include "javascriptgrammar_p.h"
+#include "javascriptast_p.h"
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class JavaScriptEnginePrivate;
+class JavaScriptNameIdImpl;
+
+class JavaScriptParser: protected JavaScriptGrammar
+{
+public:
+ union Value {
+ int ival;
+ double dval;
+ JavaScriptNameIdImpl *sval;
+ JavaScript::AST::ArgumentList *ArgumentList;
+ JavaScript::AST::CaseBlock *CaseBlock;
+ JavaScript::AST::CaseClause *CaseClause;
+ JavaScript::AST::CaseClauses *CaseClauses;
+ JavaScript::AST::Catch *Catch;
+ JavaScript::AST::DefaultClause *DefaultClause;
+ JavaScript::AST::ElementList *ElementList;
+ JavaScript::AST::Elision *Elision;
+ JavaScript::AST::ExpressionNode *Expression;
+ JavaScript::AST::Finally *Finally;
+ JavaScript::AST::FormalParameterList *FormalParameterList;
+ JavaScript::AST::FunctionBody *FunctionBody;
+ JavaScript::AST::FunctionDeclaration *FunctionDeclaration;
+ JavaScript::AST::Node *Node;
+ JavaScript::AST::PropertyName *PropertyName;
+ JavaScript::AST::PropertyNameAndValueList *PropertyNameAndValueList;
+ JavaScript::AST::SourceElement *SourceElement;
+ JavaScript::AST::SourceElements *SourceElements;
+ JavaScript::AST::Statement *Statement;
+ JavaScript::AST::StatementList *StatementList;
+ JavaScript::AST::Block *Block;
+ JavaScript::AST::VariableDeclaration *VariableDeclaration;
+ JavaScript::AST::VariableDeclarationList *VariableDeclarationList;
+
+ JavaScript::AST::UiProgram *UiProgram;
+ JavaScript::AST::UiImportList *UiImportList;
+ JavaScript::AST::UiImport *UiImport;
+ JavaScript::AST::UiPublicMember *UiPublicMember;
+ JavaScript::AST::UiObjectDefinition *UiObjectDefinition;
+ JavaScript::AST::UiObjectInitializer *UiObjectInitializer;
+ JavaScript::AST::UiObjectBinding *UiObjectBinding;
+ JavaScript::AST::UiScriptBinding *UiScriptBinding;
+ JavaScript::AST::UiArrayBinding *UiArrayBinding;
+ JavaScript::AST::UiObjectMember *UiObjectMember;
+ JavaScript::AST::UiObjectMemberList *UiObjectMemberList;
+ JavaScript::AST::UiQualifiedId *UiQualifiedId;
+ };
+
+ struct DiagnosticMessage {
+ enum Kind { Warning, Error };
+
+ DiagnosticMessage()
+ : kind(Error) {}
+
+ DiagnosticMessage(Kind kind, const JavaScript::AST::SourceLocation &loc, const QString &message)
+ : kind(kind), loc(loc), message(message) {}
+
+ bool isWarning() const
+ { return kind == Warning; }
+
+ bool isError() const
+ { return kind == Error; }
+
+ Kind kind;
+ JavaScript::AST::SourceLocation loc;
+ QString message;
+ };
+
+public:
+ JavaScriptParser();
+ ~JavaScriptParser();
+
+ bool parse(JavaScriptEnginePrivate *driver);
+
+ JavaScript::AST::UiProgram *ast()
+ { return program; }
+
+ QList<DiagnosticMessage> diagnosticMessages() const
+ { return diagnostic_messages; }
+
+ inline DiagnosticMessage diagnosticMessage() const
+ {
+ foreach (const DiagnosticMessage &d, diagnostic_messages) {
+ if (! d.kind == DiagnosticMessage::Warning)
+ return d;
+ }
+
+ return DiagnosticMessage();
+ }
+
+ inline QString errorMessage() const
+ { return diagnosticMessage().message; }
+
+ inline int errorLineNumber() const
+ { return diagnosticMessage().loc.startLine; }
+
+ inline int errorColumnNumber() const
+ { return diagnosticMessage().loc.startColumn; }
+
+protected:
+ void reallocateStack();
+
+ inline Value &sym(int index)
+ { return sym_stack [tos + index - 1]; }
+
+ inline JavaScript::AST::SourceLocation &loc(int index)
+ { return location_stack [tos + index - 1]; }
+
+protected:
+ int tos;
+ int stack_size;
+ Value *sym_stack;
+ int *state_stack;
+ JavaScript::AST::SourceLocation *location_stack;
+
+ JavaScript::AST::UiProgram *program;
+
+ // error recovery
+ enum { TOKEN_BUFFER_SIZE = 3 };
+
+ struct SavedToken {
+ int token;
+ double dval;
+ JavaScript::AST::SourceLocation loc;
+ };
+
+ double yylval;
+ JavaScript::AST::SourceLocation yylloc;
+ JavaScript::AST::SourceLocation yyprevlloc;
+
+ SavedToken token_buffer[TOKEN_BUFFER_SIZE];
+ SavedToken *first_token;
+ SavedToken *last_token;
+
+ QList<DiagnosticMessage> diagnostic_messages;
+};
+
+
+#define J_SCRIPT_REGEXPLITERAL_RULE1 52
+
+#define J_SCRIPT_REGEXPLITERAL_RULE2 53
+
+QT_END_NAMESPACE
+
+
+
+#endif // JAVASCRIPTPARSER_P_H
diff --git a/src/declarative/qml/parser/javascriptprettypretty.cpp b/src/declarative/qml/parser/javascriptprettypretty.cpp
new file mode 100644
index 0000000..6e632b7
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptprettypretty.cpp
@@ -0,0 +1,1334 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "javascriptprettypretty_p.h"
+
+
+
+#include "javascriptengine_p.h"
+
+
+
+
+#include "javascriptast_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QTextStream>
+#include <QtCore/QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace JavaScript {
+QString numberToString(qjsreal value);
+}
+
+using namespace JavaScript;
+
+PrettyPretty::PrettyPretty(QTextStream &o):
+ out(o), m_indentLevel(0)
+{
+}
+
+PrettyPretty::~PrettyPretty()
+{
+}
+
+void PrettyPretty::acceptAsBlock(AST::Node *node)
+{
+ out << "{";
+ pushIndentLevel();
+ newlineAndIndent();
+ accept(node);
+ popIndentLevel();
+ newlineAndIndent();
+ out << "}";
+}
+
+int PrettyPretty::operatorPrecedenceLevel(int op)
+{
+ switch (op) {
+ case QSOperator::Div:
+ case QSOperator::Mod:
+ case QSOperator::Mul:
+ return 5;
+ case QSOperator::Add:
+ case QSOperator::Sub:
+ return 6;
+ case QSOperator::LShift:
+ case QSOperator::RShift:
+ case QSOperator::URShift:
+ return 7;
+ case QSOperator::Ge:
+ case QSOperator::Gt:
+ case QSOperator::In:
+ case QSOperator::InstanceOf:
+ case QSOperator::Le:
+ case QSOperator::Lt:
+ return 8;
+ case QSOperator::Equal:
+ case QSOperator::NotEqual:
+ case QSOperator::StrictEqual:
+ case QSOperator::StrictNotEqual:
+ return 9;
+ case QSOperator::BitAnd:
+ return 10;
+ case QSOperator::BitXor:
+ return 11;
+ case QSOperator::BitOr:
+ return 12;
+ case QSOperator::And:
+ return 13;
+ case QSOperator::Or:
+ return 14;
+ case QSOperator::InplaceAnd:
+ case QSOperator::InplaceSub:
+ case QSOperator::InplaceDiv:
+ case QSOperator::InplaceAdd:
+ case QSOperator::InplaceLeftShift:
+ case QSOperator::InplaceMod:
+ case QSOperator::InplaceMul:
+ case QSOperator::InplaceOr:
+ case QSOperator::InplaceRightShift:
+ case QSOperator::InplaceURightShift:
+ case QSOperator::InplaceXor:
+ case QSOperator::Assign:
+ return 16;
+ default:
+ Q_ASSERT_X(false, "PrettyPretty::operatorPrecedenceLevel()", "bad operator");
+ }
+ return 0;
+}
+
+int PrettyPretty::compareOperatorPrecedence(int op1, int op2)
+{
+ int prec1 = operatorPrecedenceLevel(op1);
+ int prec2 = operatorPrecedenceLevel(op2);
+ if (prec1 == prec2)
+ return 0;
+ if (prec1 > prec2)
+ return -1;
+ return 1;
+}
+
+QTextStream &PrettyPretty::operator () (AST::Node *node, int level)
+{
+ int was = indentLevel(level);
+ accept(node);
+ indentLevel(was);
+ return out;
+}
+
+QTextStream &PrettyPretty::newlineAndIndent()
+{
+ enum { IND = 4 };
+ out << endl << QString().fill(QLatin1Char(' '), m_indentLevel * IND);
+ return out;
+}
+
+void PrettyPretty::accept(AST::Node *node)
+{
+ AST::Node::acceptChild(node, this);
+}
+
+bool PrettyPretty::visit(AST::ThisExpression *node)
+{
+ Q_UNUSED(node);
+ out << "this";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::ThisExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::IdentifierExpression *node)
+{
+ out << JavaScriptEnginePrivate::toString(node->name);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::IdentifierExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::NullExpression *node)
+{
+ Q_UNUSED(node);
+ out << "null";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::NullExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::TrueLiteral *node)
+{
+ Q_UNUSED(node);
+ out << "true";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::TrueLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FalseLiteral *node)
+{
+ Q_UNUSED(node);
+ out << "false";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::FalseLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::StringLiteral *node)
+{
+ QString lit = JavaScriptEnginePrivate::toString(node->value);
+ lit.replace(QLatin1String("\\"), QLatin1String("\\\\"));
+ out << "\"" << lit << "\"";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::StringLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::NumericLiteral *node)
+{
+ out << JavaScript::numberToString(node->value);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::NumericLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::RegExpLiteral *node)
+{
+ out << "/" << JavaScriptEnginePrivate::toString(node->pattern) << "/";
+ if (node->flags)
+ out << JavaScript::Ecma::RegExp::flagsToString(node->flags);
+
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::RegExpLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ArrayLiteral *node)
+{
+ out << "[";
+ accept(node->elements);
+ accept(node->elision);
+ out << "]";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ArrayLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ObjectLiteral *node)
+{
+ out << "{";
+ if (node->properties) {
+ pushIndentLevel();
+ AST::PropertyNameAndValueList *prop;
+ for (prop = node->properties; prop != 0; prop = prop->next) {
+ newlineAndIndent();
+ accept(prop);
+ if (prop->next)
+ out << ",";
+ }
+ popIndentLevel();
+ newlineAndIndent();
+ }
+ out << "}";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ObjectLiteral *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ElementList *node)
+{
+ accept(node->elision);
+ accept(node->expression);
+ for (node = node->next; node != 0; node = node->next) {
+ out << ", ";
+ accept(node->elision);
+ accept(node->expression);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ElementList *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::Elision *node)
+{
+ out << ", ";
+ for (AST::Elision *eit = node->next; eit != 0; eit = eit->next)
+ out << ", ";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::Elision *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::PropertyNameAndValueList *node)
+{
+ accept(node->name);
+ out << ": ";
+ accept(node->value);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::PropertyNameAndValueList *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::IdentifierPropertyName *node)
+{
+ out << JavaScriptEnginePrivate::toString(node->id);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::IdentifierPropertyName *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::StringLiteralPropertyName *node)
+{
+ QString lit = JavaScriptEnginePrivate::toString(node->id);
+ lit.replace(QLatin1String("\\"), QLatin1String("\\\\"));
+ out << lit;
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::StringLiteralPropertyName *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::NumericLiteralPropertyName *node)
+{
+ out << node->id;
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::NumericLiteralPropertyName *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ArrayMemberExpression *node)
+{
+ accept(node->base);
+ out << "[";
+ accept(node->expression);
+ out << "]";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ArrayMemberExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FieldMemberExpression *node)
+{
+ accept(node->base);
+ out << "." << JavaScriptEnginePrivate::toString(node->name);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::FieldMemberExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::NewMemberExpression *node)
+{
+ out << "new ";
+ accept(node->base);
+ out << "(";
+ accept(node->arguments);
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::NewMemberExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::NewExpression *node)
+{
+ Q_UNUSED(node);
+ out << "new ";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::NewExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::CallExpression *node)
+{
+ accept(node->base);
+ out << "(";
+ accept(node->arguments);
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::CallExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ArgumentList *node)
+{
+ accept(node->expression);
+ for (node = node->next; node != 0; node = node->next) {
+ out << ", ";
+ accept(node->expression);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ArgumentList *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::PostIncrementExpression *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::PostIncrementExpression *node)
+{
+ Q_UNUSED(node);
+ out << "++";
+}
+
+bool PrettyPretty::visit(AST::PostDecrementExpression *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::PostDecrementExpression *node)
+{
+ Q_UNUSED(node);
+ out << "--";
+}
+
+bool PrettyPretty::visit(AST::DeleteExpression *node)
+{
+ Q_UNUSED(node);
+ out << "delete ";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::DeleteExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::VoidExpression *node)
+{
+ Q_UNUSED(node);
+ out << "void ";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::VoidExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::TypeOfExpression *node)
+{
+ Q_UNUSED(node);
+ out << "typeof ";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::TypeOfExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::PreIncrementExpression *node)
+{
+ Q_UNUSED(node);
+ out << "++";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::PreIncrementExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::PreDecrementExpression *node)
+{
+ Q_UNUSED(node);
+ out << "--";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::PreDecrementExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::UnaryPlusExpression *node)
+{
+ out << "+";
+ bool needParens = (node->expression->binaryExpressionCast() != 0);
+ if (needParens)
+ out << "(";
+ accept(node->expression);
+ if (needParens)
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::UnaryPlusExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::UnaryMinusExpression *node)
+{
+ out << "-";
+ bool needParens = (node->expression->binaryExpressionCast() != 0);
+ if (needParens)
+ out << "(";
+ accept(node->expression);
+ if (needParens)
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::UnaryMinusExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::TildeExpression *node)
+{
+ out << "~";
+ bool needParens = (node->expression->binaryExpressionCast() != 0);
+ if (needParens)
+ out << "(";
+ accept(node->expression);
+ if (needParens)
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::TildeExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::NotExpression *node)
+{
+ out << "!";
+ bool needParens = (node->expression->binaryExpressionCast() != 0);
+ if (needParens)
+ out << "(";
+ accept(node->expression);
+ if (needParens)
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::NotExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::BinaryExpression *node)
+{
+ bool needParens = node->left->binaryExpressionCast()
+ && (compareOperatorPrecedence(node->left->binaryExpressionCast()->op, node->op) < 0);
+ if (needParens)
+ out << "(";
+ accept(node->left);
+ if (needParens)
+ out << ")";
+ QString s;
+ switch (node->op) {
+ case QSOperator::Add:
+ s = QLatin1String("+"); break;
+ case QSOperator::And:
+ s = QLatin1String("&&"); break;
+ case QSOperator::InplaceAnd:
+ s = QLatin1String("&="); break;
+ case QSOperator::Assign:
+ s = QLatin1String("="); break;
+ case QSOperator::BitAnd:
+ s = QLatin1String("&"); break;
+ case QSOperator::BitOr:
+ s = QLatin1String("|"); break;
+ case QSOperator::BitXor:
+ s = QLatin1String("^"); break;
+ case QSOperator::InplaceSub:
+ s = QLatin1String("-="); break;
+ case QSOperator::Div:
+ s = QLatin1String("/"); break;
+ case QSOperator::InplaceDiv:
+ s = QLatin1String("/="); break;
+ case QSOperator::Equal:
+ s = QLatin1String("=="); break;
+ case QSOperator::Ge:
+ s = QLatin1String(">="); break;
+ case QSOperator::Gt:
+ s = QLatin1String(">"); break;
+ case QSOperator::In:
+ s = QLatin1String("in"); break;
+ case QSOperator::InplaceAdd:
+ s = QLatin1String("+="); break;
+ case QSOperator::InstanceOf:
+ s = QLatin1String("instanceof"); break;
+ case QSOperator::Le:
+ s = QLatin1String("<="); break;
+ case QSOperator::LShift:
+ s = QLatin1String("<<"); break;
+ case QSOperator::InplaceLeftShift:
+ s = QLatin1String("<<="); break;
+ case QSOperator::Lt:
+ s = QLatin1String("<"); break;
+ case QSOperator::Mod:
+ s = QLatin1String("%"); break;
+ case QSOperator::InplaceMod:
+ s = QLatin1String("%="); break;
+ case QSOperator::Mul:
+ s = QLatin1String("*"); break;
+ case QSOperator::InplaceMul:
+ s = QLatin1String("*="); break;
+ case QSOperator::NotEqual:
+ s = QLatin1String("!="); break;
+ case QSOperator::Or:
+ s = QLatin1String("||"); break;
+ case QSOperator::InplaceOr:
+ s = QLatin1String("|="); break;
+ case QSOperator::RShift:
+ s = QLatin1String(">>"); break;
+ case QSOperator::InplaceRightShift:
+ s = QLatin1String(">>="); break;
+ case QSOperator::StrictEqual:
+ s = QLatin1String("==="); break;
+ case QSOperator::StrictNotEqual:
+ s = QLatin1String("!=="); break;
+ case QSOperator::Sub:
+ s = QLatin1String("-"); break;
+ case QSOperator::URShift:
+ s = QLatin1String(">>>"); break;
+ case QSOperator::InplaceURightShift:
+ s = QLatin1String(">>>="); break;
+ case QSOperator::InplaceXor:
+ s = QLatin1String("^="); break;
+ default:
+ Q_ASSERT (0);
+ }
+ out << " " << s << " ";
+ needParens = node->right->binaryExpressionCast()
+ && (compareOperatorPrecedence(node->right->binaryExpressionCast()->op, node->op) <= 0);
+ if (needParens)
+ out << "(";
+ accept(node->right);
+ if (needParens)
+ out << ")";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::BinaryExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ConditionalExpression *node)
+{
+ accept(node->expression);
+ out << " ? ";
+ accept(node->ok);
+ out << " : ";
+ accept(node->ko);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ConditionalExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::Expression *node)
+{
+ accept(node->left);
+ out << ", ";
+ accept(node->right);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::Expression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::Block *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::Block *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::StatementList *node)
+{
+ accept(node->statement);
+ for (node = node->next; node != 0; node = node->next) {
+ newlineAndIndent();
+ accept(node->statement);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::StatementList *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::VariableDeclarationList *node)
+{
+ AST::VariableDeclarationList *it = node;
+
+ do {
+ it->declaration->accept(this);
+ it = it->next;
+ if (it)
+ out << ", ";
+ } while (it);
+
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::VariableDeclarationList *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::VariableStatement *node)
+{
+ out << "var ";
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::VariableStatement *node)
+{
+ Q_UNUSED(node);
+ out << ";";
+}
+
+bool PrettyPretty::visit(AST::VariableDeclaration *node)
+{
+ out << JavaScriptEnginePrivate::toString(node->name);
+ if (node->expression) {
+ out << " = ";
+ accept(node->expression);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::VariableDeclaration *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::EmptyStatement *node)
+{
+ Q_UNUSED(node);
+ out << ";";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::EmptyStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ExpressionStatement *node)
+{
+ accept(node->expression);
+ out << ";";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ExpressionStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::IfStatement *node)
+{
+ out << "if (";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->ok);
+ if (node->ko) {
+ out << " else ";
+ acceptAsBlock(node->ko);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::IfStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::DoWhileStatement *node)
+{
+ out << "do ";
+ acceptAsBlock(node->statement);
+ out << " while (";
+ accept(node->expression);
+ out << ");";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::DoWhileStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::WhileStatement *node)
+{
+ out << "while (";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->statement);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::WhileStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ForStatement *node)
+{
+ out << "for (";
+ accept(node->initialiser);
+ out << "; ";
+ accept(node->condition);
+ out << "; ";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->statement);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ForStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::LocalForStatement *node)
+{
+ out << "for (var ";
+ accept(node->declarations);
+ out << "; ";
+ accept(node->condition);
+ out << "; ";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->statement);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::LocalForStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ForEachStatement *node)
+{
+ out << "for (";
+ accept(node->initialiser);
+ out << " in ";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->statement);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ForEachStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::LocalForEachStatement *node)
+{
+ out << "for (var ";
+ accept(node->declaration);
+ out << " in ";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->statement);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::LocalForEachStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ContinueStatement *node)
+{
+ out << "continue";
+ if (node->label) {
+ out << " " << JavaScriptEnginePrivate::toString(node->label);
+ }
+ out << ";";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ContinueStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::BreakStatement *node)
+{
+ out << "break";
+ if (node->label) {
+ out << " " << JavaScriptEnginePrivate::toString(node->label);
+ }
+ out << ";";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::BreakStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ReturnStatement *node)
+{
+ out << "return";
+ if (node->expression) {
+ out << " ";
+ accept(node->expression);
+ }
+ out << ";";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ReturnStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::WithStatement *node)
+{
+ out << "with (";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->statement);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::WithStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::SwitchStatement *node)
+{
+ out << "switch (";
+ accept(node->expression);
+ out << ") ";
+ acceptAsBlock(node->block);
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::SwitchStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::CaseBlock *node)
+{
+ accept(node->clauses);
+ if (node->defaultClause) {
+ newlineAndIndent();
+ accept(node->defaultClause);
+ }
+ if (node->moreClauses) {
+ newlineAndIndent();
+ accept(node->moreClauses);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::CaseBlock *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::CaseClauses *node)
+{
+ accept(node->clause);
+ for (node = node->next; node != 0; node = node->next) {
+ newlineAndIndent();
+ accept(node->clause);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::CaseClauses *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::CaseClause *node)
+{
+ out << "case ";
+ accept(node->expression);
+ out << ":";
+ if (node->statements) {
+ newlineAndIndent();
+ accept(node->statements);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::CaseClause *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::DefaultClause *node)
+{
+ Q_UNUSED(node);
+ out << "default:";
+ newlineAndIndent();
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::DefaultClause *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::LabelledStatement *node)
+{
+ out << JavaScriptEnginePrivate::toString(node->label) << ": ";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::LabelledStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::ThrowStatement *node)
+{
+ Q_UNUSED(node);
+ out << "throw ";
+ accept(node->expression);
+ out << ";";
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::ThrowStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::TryStatement *node)
+{
+ out << "try ";
+ acceptAsBlock(node->statement);
+ if (node->catchExpression) {
+ out << " catch (" << JavaScriptEnginePrivate::toString(node->catchExpression->name) << ") ";
+ acceptAsBlock(node->catchExpression->statement);
+ }
+ if (node->finallyExpression) {
+ out << " finally ";
+ acceptAsBlock(node->finallyExpression->statement);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::TryStatement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::Catch *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::Catch *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::Finally *node)
+{
+ Q_UNUSED(node);
+ out << "finally ";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::Finally *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FunctionDeclaration *node)
+{
+ out << "function";
+
+ if (node->name)
+ out << " " << JavaScriptEnginePrivate::toString(node->name);
+
+ // the arguments
+ out << "(";
+ for (AST::FormalParameterList *it = node->formals; it; it = it->next) {
+ if (it->name)
+ out << JavaScriptEnginePrivate::toString(it->name);
+
+ if (it->next)
+ out << ", ";
+ }
+ out << ")";
+
+ // the function body
+ out << " {";
+
+ if (node->body) {
+ pushIndentLevel();
+ newlineAndIndent();
+ accept(node->body);
+ popIndentLevel();
+ newlineAndIndent();
+ }
+
+ out << "}";
+
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::FunctionDeclaration *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FunctionExpression *node)
+{
+ out << "function";
+
+ if (node->name)
+ out << " " << JavaScriptEnginePrivate::toString(node->name);
+
+ // the arguments
+ out << "(";
+ for (AST::FormalParameterList *it = node->formals; it; it = it->next) {
+ if (it->name)
+ out << JavaScriptEnginePrivate::toString(it->name);
+
+ if (it->next)
+ out << ", ";
+ }
+ out << ")";
+
+ // the function body
+ out << " {";
+
+ if (node->body) {
+ pushIndentLevel();
+ newlineAndIndent();
+ accept(node->body);
+ popIndentLevel();
+ newlineAndIndent();
+ }
+
+ out << "}";
+
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::FunctionExpression *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FormalParameterList *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::FormalParameterList *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FunctionBody *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::FunctionBody *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::Program *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::Program *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::SourceElements *node)
+{
+ Q_UNUSED(node);
+ accept(node->element);
+ for (node = node->next; node != 0; node = node->next) {
+ newlineAndIndent();
+ accept(node->element);
+ }
+ return false;
+}
+
+void PrettyPretty::endVisit(AST::SourceElements *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::FunctionSourceElement *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::FunctionSourceElement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::StatementSourceElement *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::StatementSourceElement *node)
+{
+ Q_UNUSED(node);
+}
+
+bool PrettyPretty::visit(AST::DebuggerStatement *node)
+{
+ Q_UNUSED(node);
+ out << "debugger";
+ return true;
+}
+
+void PrettyPretty::endVisit(AST::DebuggerStatement *node)
+{
+ Q_UNUSED(node);
+ out << ";";
+}
+
+bool PrettyPretty::preVisit(AST::Node *node)
+{
+ Q_UNUSED(node);
+ return true;
+}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/javascriptprettypretty_p.h b/src/declarative/qml/parser/javascriptprettypretty_p.h
new file mode 100644
index 0000000..c692da5
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptprettypretty_p.h
@@ -0,0 +1,329 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPTPRETTYPRETTY_P_H
+#define JAVASCRIPTPRETTYPRETTY_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/qglobal.h>
+
+#include "javascriptastvisitor_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QTextStream;
+
+namespace JavaScript {
+
+class PrettyPretty: protected AST::Visitor
+{
+public:
+ PrettyPretty(QTextStream &out);
+ virtual ~PrettyPretty();
+
+ QTextStream &operator () (AST::Node *node, int level = 0);
+
+protected:
+ void accept(AST::Node *node);
+
+ virtual bool preVisit(AST::Node *node);
+
+ virtual bool visit(AST::ThisExpression *node);
+ virtual void endVisit(AST::ThisExpression *node);
+
+ virtual bool visit(AST::IdentifierExpression *node);
+ virtual void endVisit(AST::IdentifierExpression *node);
+
+ virtual bool visit(AST::NullExpression *node);
+ virtual void endVisit(AST::NullExpression *node);
+
+ virtual bool visit(AST::TrueLiteral *node);
+ virtual void endVisit(AST::TrueLiteral *node);
+
+ virtual bool visit(AST::FalseLiteral *node);
+ virtual void endVisit(AST::FalseLiteral *node);
+
+ virtual bool visit(AST::StringLiteral *node);
+ virtual void endVisit(AST::StringLiteral *node);
+
+ virtual bool visit(AST::NumericLiteral *node);
+ virtual void endVisit(AST::NumericLiteral *node);
+
+ virtual bool visit(AST::RegExpLiteral *node);
+ virtual void endVisit(AST::RegExpLiteral *node);
+
+ virtual bool visit(AST::ArrayLiteral *node);
+ virtual void endVisit(AST::ArrayLiteral *node);
+
+ virtual bool visit(AST::ObjectLiteral *node);
+ virtual void endVisit(AST::ObjectLiteral *node);
+
+ virtual bool visit(AST::ElementList *node);
+ virtual void endVisit(AST::ElementList *node);
+
+ virtual bool visit(AST::Elision *node);
+ virtual void endVisit(AST::Elision *node);
+
+ virtual bool visit(AST::PropertyNameAndValueList *node);
+ virtual void endVisit(AST::PropertyNameAndValueList *node);
+
+ virtual bool visit(AST::IdentifierPropertyName *node);
+ virtual void endVisit(AST::IdentifierPropertyName *node);
+
+ virtual bool visit(AST::StringLiteralPropertyName *node);
+ virtual void endVisit(AST::StringLiteralPropertyName *node);
+
+ virtual bool visit(AST::NumericLiteralPropertyName *node);
+ virtual void endVisit(AST::NumericLiteralPropertyName *node);
+
+ virtual bool visit(AST::ArrayMemberExpression *node);
+ virtual void endVisit(AST::ArrayMemberExpression *node);
+
+ virtual bool visit(AST::FieldMemberExpression *node);
+ virtual void endVisit(AST::FieldMemberExpression *node);
+
+ virtual bool visit(AST::NewMemberExpression *node);
+ virtual void endVisit(AST::NewMemberExpression *node);
+
+ virtual bool visit(AST::NewExpression *node);
+ virtual void endVisit(AST::NewExpression *node);
+
+ virtual bool visit(AST::CallExpression *node);
+ virtual void endVisit(AST::CallExpression *node);
+
+ virtual bool visit(AST::ArgumentList *node);
+ virtual void endVisit(AST::ArgumentList *node);
+
+ virtual bool visit(AST::PostIncrementExpression *node);
+ virtual void endVisit(AST::PostIncrementExpression *node);
+
+ virtual bool visit(AST::PostDecrementExpression *node);
+ virtual void endVisit(AST::PostDecrementExpression *node);
+
+ virtual bool visit(AST::DeleteExpression *node);
+ virtual void endVisit(AST::DeleteExpression *node);
+
+ virtual bool visit(AST::VoidExpression *node);
+ virtual void endVisit(AST::VoidExpression *node);
+
+ virtual bool visit(AST::TypeOfExpression *node);
+ virtual void endVisit(AST::TypeOfExpression *node);
+
+ virtual bool visit(AST::PreIncrementExpression *node);
+ virtual void endVisit(AST::PreIncrementExpression *node);
+
+ virtual bool visit(AST::PreDecrementExpression *node);
+ virtual void endVisit(AST::PreDecrementExpression *node);
+
+ virtual bool visit(AST::UnaryPlusExpression *node);
+ virtual void endVisit(AST::UnaryPlusExpression *node);
+
+ virtual bool visit(AST::UnaryMinusExpression *node);
+ virtual void endVisit(AST::UnaryMinusExpression *node);
+
+ virtual bool visit(AST::TildeExpression *node);
+ virtual void endVisit(AST::TildeExpression *node);
+
+ virtual bool visit(AST::NotExpression *node);
+ virtual void endVisit(AST::NotExpression *node);
+
+ virtual bool visit(AST::BinaryExpression *node);
+ virtual void endVisit(AST::BinaryExpression *node);
+
+ virtual bool visit(AST::ConditionalExpression *node);
+ virtual void endVisit(AST::ConditionalExpression *node);
+
+ virtual bool visit(AST::Expression *node);
+ virtual void endVisit(AST::Expression *node);
+
+ virtual bool visit(AST::Block *node);
+ virtual void endVisit(AST::Block *node);
+
+ virtual bool visit(AST::StatementList *node);
+ virtual void endVisit(AST::StatementList *node);
+
+ virtual bool visit(AST::VariableStatement *node);
+ virtual void endVisit(AST::VariableStatement *node);
+
+ virtual bool visit(AST::VariableDeclarationList *node);
+ virtual void endVisit(AST::VariableDeclarationList *node);
+
+ virtual bool visit(AST::VariableDeclaration *node);
+ virtual void endVisit(AST::VariableDeclaration *node);
+
+ virtual bool visit(AST::EmptyStatement *node);
+ virtual void endVisit(AST::EmptyStatement *node);
+
+ virtual bool visit(AST::ExpressionStatement *node);
+ virtual void endVisit(AST::ExpressionStatement *node);
+
+ virtual bool visit(AST::IfStatement *node);
+ virtual void endVisit(AST::IfStatement *node);
+
+ virtual bool visit(AST::DoWhileStatement *node);
+ virtual void endVisit(AST::DoWhileStatement *node);
+
+ virtual bool visit(AST::WhileStatement *node);
+ virtual void endVisit(AST::WhileStatement *node);
+
+ virtual bool visit(AST::ForStatement *node);
+ virtual void endVisit(AST::ForStatement *node);
+
+ virtual bool visit(AST::LocalForStatement *node);
+ virtual void endVisit(AST::LocalForStatement *node);
+
+ virtual bool visit(AST::ForEachStatement *node);
+ virtual void endVisit(AST::ForEachStatement *node);
+
+ virtual bool visit(AST::LocalForEachStatement *node);
+ virtual void endVisit(AST::LocalForEachStatement *node);
+
+ virtual bool visit(AST::ContinueStatement *node);
+ virtual void endVisit(AST::ContinueStatement *node);
+
+ virtual bool visit(AST::BreakStatement *node);
+ virtual void endVisit(AST::BreakStatement *node);
+
+ virtual bool visit(AST::ReturnStatement *node);
+ virtual void endVisit(AST::ReturnStatement *node);
+
+ virtual bool visit(AST::WithStatement *node);
+ virtual void endVisit(AST::WithStatement *node);
+
+ virtual bool visit(AST::SwitchStatement *node);
+ virtual void endVisit(AST::SwitchStatement *node);
+
+ virtual bool visit(AST::CaseBlock *node);
+ virtual void endVisit(AST::CaseBlock *node);
+
+ virtual bool visit(AST::CaseClauses *node);
+ virtual void endVisit(AST::CaseClauses *node);
+
+ virtual bool visit(AST::CaseClause *node);
+ virtual void endVisit(AST::CaseClause *node);
+
+ virtual bool visit(AST::DefaultClause *node);
+ virtual void endVisit(AST::DefaultClause *node);
+
+ virtual bool visit(AST::LabelledStatement *node);
+ virtual void endVisit(AST::LabelledStatement *node);
+
+ virtual bool visit(AST::ThrowStatement *node);
+ virtual void endVisit(AST::ThrowStatement *node);
+
+ virtual bool visit(AST::TryStatement *node);
+ virtual void endVisit(AST::TryStatement *node);
+
+ virtual bool visit(AST::Catch *node);
+ virtual void endVisit(AST::Catch *node);
+
+ virtual bool visit(AST::Finally *node);
+ virtual void endVisit(AST::Finally *node);
+
+ virtual bool visit(AST::FunctionDeclaration *node);
+ virtual void endVisit(AST::FunctionDeclaration *node);
+
+ virtual bool visit(AST::FunctionExpression *node);
+ virtual void endVisit(AST::FunctionExpression *node);
+
+ virtual bool visit(AST::FormalParameterList *node);
+ virtual void endVisit(AST::FormalParameterList *node);
+
+ virtual bool visit(AST::FunctionBody *node);
+ virtual void endVisit(AST::FunctionBody *node);
+
+ virtual bool visit(AST::Program *node);
+ virtual void endVisit(AST::Program *node);
+
+ virtual bool visit(AST::SourceElements *node);
+ virtual void endVisit(AST::SourceElements *node);
+
+ virtual bool visit(AST::FunctionSourceElement *node);
+ virtual void endVisit(AST::FunctionSourceElement *node);
+
+ virtual bool visit(AST::StatementSourceElement *node);
+ virtual void endVisit(AST::StatementSourceElement *node);
+
+ virtual bool visit(AST::DebuggerStatement *node);
+ virtual void endVisit(AST::DebuggerStatement *node);
+
+ int indentLevel(int level)
+ {
+ int was = m_indentLevel;
+ m_indentLevel = level;
+ return was;
+ }
+
+ void pushIndentLevel()
+ { ++m_indentLevel; }
+
+ void popIndentLevel()
+ { --m_indentLevel; }
+
+ QTextStream &newlineAndIndent();
+
+ void acceptAsBlock(AST::Node *node);
+
+ static int operatorPrecedenceLevel(int op);
+ static int compareOperatorPrecedence(int op1, int op2);
+
+private:
+ QTextStream &out;
+ int m_indentLevel;
+
+ Q_DISABLE_COPY(PrettyPretty)
+};
+
+} // namespace JavaScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/javascriptvalue.h b/src/declarative/qml/parser/javascriptvalue.h
new file mode 100644
index 0000000..c68b817
--- /dev/null
+++ b/src/declarative/qml/parser/javascriptvalue.h
@@ -0,0 +1,6 @@
+#ifndef JAVASCRIPTVALUE_H
+#define JAVASCRIPTVALUE_H
+
+typedef double qjsreal;
+
+#endif // JAVASCRIPTVALUE_H
diff --git a/src/declarative/qml/parser/parser.pri b/src/declarative/qml/parser/parser.pri
new file mode 100644
index 0000000..130aeaf
--- /dev/null
+++ b/src/declarative/qml/parser/parser.pri
@@ -0,0 +1,21 @@
+
+HEADERS += $$PWD/javascriptast_p.h \
+ $$PWD/javascriptastfwd_p.h \
+ $$PWD/javascriptastvisitor_p.h \
+ $$PWD/javascriptengine_p.h \
+ $$PWD/javascriptgrammar_p.h \
+ $$PWD/javascriptlexer_p.h \
+ $$PWD/javascriptmemorypool_p.h \
+ $$PWD/javascriptnodepool_p.h \
+ $$PWD/javascriptparser_p.h \
+ $$PWD/javascriptprettypretty_p.h \
+ $$PWD/javascriptvalue.h \
+
+SOURCES += $$PWD/javascriptast.cpp \
+ $$PWD/javascriptastvisitor.cpp \
+ $$PWD/javascriptengine_p.cpp \
+ $$PWD/javascriptgrammar.cpp \
+ $$PWD/javascriptlexer.cpp \
+ $$PWD/javascriptprettypretty.cpp \
+ $$PWD/javascriptparser.cpp
+
diff --git a/src/declarative/qml/qml.h b/src/declarative/qml/qml.h
new file mode 100644
index 0000000..1c662a7
--- /dev/null
+++ b/src/declarative/qml/qml.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QML_H
+#define QML_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qmetaobject.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qmlmetatype.h>
+#include <QtDeclarative/qmlmetaproperty.h>
+#include <QtDeclarative/qmlparserstatus.h>
+#include <QtDeclarative/qmllist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+#define QML_DECLARE_TYPE(TYPE) \
+ Q_DECLARE_METATYPE(TYPE *); \
+ Q_DECLARE_METATYPE(QList<TYPE *> *); \
+ Q_DECLARE_METATYPE(QmlList<TYPE *> *);
+
+#define QML_DECLARE_TYPE_HASMETATYPE(TYPE) \
+ Q_DECLARE_METATYPE(QList<TYPE *> *); \
+ Q_DECLARE_METATYPE(QmlList<TYPE *> *);
+
+#define QML_DECLARE_INTERFACE(INTERFACE) \
+ QML_DECLARE_TYPE(INTERFACE)
+
+#define QML_DECLARE_INTERFACE_HASMETATYPE(INTERFACE) \
+ QML_DECLARE_TYPE_HASMETATYPE(INTERFACE)
+
+#define QML_DEFINE_INTERFACE(INTERFACE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<INTERFACE *>::instance(qmlRegisterInterface<INTERFACE>(#INTERFACE));
+
+#define QML_DEFINE_EXTENDED_TYPE(TYPE, NAME, EXTENSION) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(#NAME, #TYPE));
+
+#define QML_DEFINE_TYPE(TYPE, NAME) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterType<TYPE>(#NAME, #TYPE));
+
+#define QML_DEFINE_EXTENDED_NOCREATE_TYPE(TYPE, EXTENSION) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(#TYPE));
+
+#define QML_DEFINE_NOCREATE_TYPE(TYPE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterType<TYPE>(#TYPE));
+
+class QmlContext;
+class QmlEngine;
+Q_DECLARATIVE_EXPORT QmlContext *qmlContext(const QObject *);
+Q_DECLARATIVE_EXPORT QmlEngine *qmlEngine(const QObject *);
+Q_DECLARATIVE_EXPORT QObject *qmlAttachedPropertiesObjectById(int, const QObject *);
+
+template<typename T>
+QObject *qmlAttachedPropertiesObject(const QObject *obj)
+{
+ // ### is this threadsafe?
+ static int idx = -1;
+
+ if (idx == -1)
+ idx = QmlMetaType::attachedPropertiesFuncId(&T::staticMetaObject);
+
+ if (idx == -1 || !obj)
+ return 0;
+
+ return qmlAttachedPropertiesObjectById(obj, idx);
+}
+
+QML_DECLARE_TYPE(QObject);
+Q_DECLARE_METATYPE(QVariant);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QML_H
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
new file mode 100644
index 0000000..99e30e4
--- /dev/null
+++ b/src/declarative/qml/qml.pri
@@ -0,0 +1,73 @@
+SOURCES += qml/qmlparser.cpp \
+ qml/qmlinstruction.cpp \
+ qml/qmlvmemetaobject.cpp \
+ qml/qmlengine.cpp \
+ qml/qmlbindablevalue.cpp \
+ qml/qmlmetaproperty.cpp \
+ qml/qmlcomponent.cpp \
+ qml/qmlcontext.cpp \
+ qml/qmlcustomparser.cpp \
+ qml/qmlpropertyvaluesource.cpp \
+ qml/qmlproxymetaobject.cpp \
+ qml/qmlvme.cpp \
+ qml/qmlcompiler.cpp \
+ qml/qmlcompiledcomponent.cpp \
+ qml/qmlboundsignal.cpp \
+ qml/qmldom.cpp \
+ qml/qmlrefcount.cpp \
+ qml/qmlprivate.cpp \
+ qml/qmlmetatype.cpp \
+ qml/qmlstringconverters.cpp \
+ qml/qmlclassfactory.cpp \
+ qml/qmlparserstatus.cpp \
+ qml/qmlcompositetypemanager.cpp \
+ qml/qmlinfo.cpp \
+ qml/qmlerror.cpp
+
+HEADERS += qml/qmlparser_p.h \
+ qml/qmlinstruction_p.h \
+ qml/qmlvmemetaobject_p.h \
+ qml/qml.h \
+ qml/qmlbindablevalue.h \
+ qml/qmlbindablevalue_p.h \
+ qml/qmlmetaproperty.h \
+ qml/qmlcomponent.h \
+ qml/qmlcomponent_p.h \
+ qml/qmlcustomparser_p.h \
+ qml/qmlcustomparser_p_p.h \
+ qml/qmlpropertyvaluesource.h \
+ qml/qmlboundsignal_p.h \
+ qml/qmlparserstatus.h \
+ qml/qmlproxymetaobject_p.h \
+ qml/qmlcompiledcomponent_p.h \
+ qml/qmlvme_p.h \
+ qml/qmlcompiler_p.h \
+ qml/qmlengine_p.h \
+ qml/qmlprivate.h \
+ qml/qmldom.h \
+ qml/qmldom_p.h \
+ qml/qmlrefcount_p.h \
+ qml/qmlmetatype.h \
+ qml/qmlengine.h \
+ qml/qmlcontext.h \
+ qml/qmlexpression.h \
+ qml/qmlstringconverters_p.h \
+ qml/qmlclassfactory_p.h \
+ qml/qmlinfo.h \
+ qml/qmlmetaproperty_p.h \
+ qml/qmlcontext_p.h \
+ qml/qmlcompositetypemanager_p.h \
+ qml/qmllist.h \
+ qml/qmldeclarativedata_p.h \
+ qml/qmlerror.h
+
+# for qtscript debugger
+QT += scripttools
+include(script/script.pri)
+
+# new language front-end
+include(parser/parser.pri)
+
+HEADERS += qml/qmlscriptparser_p.h
+
+SOURCES += qml/qmlscriptparser.cpp
diff --git a/src/declarative/qml/qmlbindablevalue.cpp b/src/declarative/qml/qmlbindablevalue.cpp
new file mode 100644
index 0000000..d5157b6
--- /dev/null
+++ b/src/declarative/qml/qmlbindablevalue.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qml.h>
+#include "qmlbindablevalue.h"
+#include "qmlbindablevalue_p.h"
+#include <qmlcontext.h>
+#include <qmlinfo.h>
+#include <QVariant>
+#include <qfxperf.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS);
+
+QmlBindableValuePrivate::QmlBindableValuePrivate()
+: inited(false), updating(false), mePtr(0)
+{
+}
+
+QML_DEFINE_NOCREATE_TYPE(QmlBindableValue);
+QmlBindableValue::QmlBindableValue(QObject *parent)
+: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent)
+{
+ qFatal("QmlBindableValue: Default constructor not supported");
+}
+
+QmlBindableValue::QmlBindableValue(void *data, QmlRefCount *rc, QObject *obj, QObject *parent)
+: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent), QmlExpression(QmlContext::activeContext(), data, rc, obj)
+{
+}
+
+QmlBindableValue::QmlBindableValue(const QString &str, QObject *obj, bool sse, QObject *parent)
+: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent), QmlExpression(QmlContext::activeContext(), str, obj, sse)
+{
+}
+
+QmlBindableValue::~QmlBindableValue()
+{
+ Q_D(QmlBindableValue);
+ if(d->mePtr)
+ *(d->mePtr) = 0;
+}
+
+void QmlBindableValue::setTarget(const QmlMetaProperty &prop)
+{
+ Q_D(QmlBindableValue);
+ d->property = prop;
+
+ update();
+}
+
+QmlMetaProperty QmlBindableValue::property() const
+{
+ Q_D(const QmlBindableValue);
+ return d->property;
+}
+
+void QmlBindableValue::init()
+{
+ Q_D(QmlBindableValue);
+
+ if (d->inited)
+ return;
+ d->inited = true;
+ update();
+}
+
+void QmlBindableValue::setExpression(const QString &expr)
+{
+ QmlExpression::setExpression(expr);
+ update();
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+void QmlBindableValue::update()
+{
+ Q_D(QmlBindableValue);
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindableValueUpdate> bu;
+#endif
+ if (!d->inited)
+ return;
+
+ if (!d->updating) {
+ d->updating = true;
+
+ if (d->property.propertyCategory() == QmlMetaProperty::List) {
+ QVariant value = this->value();
+ int listType = QmlMetaType::listType(d->property.propertyType());
+
+ if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ const QList<QObject *> &list =
+ qvariant_cast<QList<QObject *> >(value);
+ QVariant listVar = d->property.read();
+ QmlMetaType::clear(listVar);
+ for (int ii = 0; ii < list.count(); ++ii) {
+ QVariant v = QmlMetaType::fromObject(list.at(ii), listType);
+ QmlMetaType::append(listVar, v);
+ }
+
+ } else if (value.type() == uint(listType) ||
+ value.userType() == listType) {
+ QVariant listVar = d->property.read();
+ QmlMetaType::clear(listVar);
+ QmlMetaType::append(listVar, value);
+ }
+ } else if (d->property.propertyCategory() == QmlMetaProperty::QmlList) {
+ // XXX - optimize!
+ QVariant value = this->value();
+ QVariant list = d->property.read();
+ QmlPrivate::ListInterface *li =
+ *(QmlPrivate::ListInterface **)list.constData();
+
+ int type = li->type();
+
+ if (QObject *obj = QmlMetaType::toQObject(value)) {
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *objMo = obj->metaObject();
+ bool found = false;
+ while(!found && objMo) {
+ if (objMo == mo)
+ found = true;
+ else
+ objMo = objMo->superClass();
+ }
+
+ if (!found) {
+ qWarning() << "Unable to assign object to list";
+ return;
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ void *d = (void *)&obj;
+ li->append(d);
+ }
+ } else if (d->property.propertyCategory() == QmlMetaProperty::Bindable) {
+
+ // NOTE: We assume that only core properties can have
+ // propertyType == Bindable
+ int idx = d->property.coreIndex();
+ Q_ASSERT(idx != -1);
+
+ void *a[1];
+ QmlBindableValue *t = this;
+ a[0] = (void *)&t;
+ d->property.object()->qt_metacall(QMetaObject::WriteProperty,
+ idx, a);
+
+ } else if (d->property.propertyCategory() == QmlMetaProperty::Object) {
+
+ QVariant value = this->value();
+ if ((int)value.type() != qMetaTypeId<QObject *>()) {
+ if (scriptWarnings()) {
+ if (!value.isValid()) {
+ qWarning() << "QmlBindableValue: Unable to assign invalid value to object property";
+ } else {
+ qWarning() << "QmlBindableValue: Unable to assign non-object to object property";
+ }
+ }
+ return;
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ QObject *obj = *(QObject **)value.data();
+
+ // NOTE: We assume that only core properties can have
+ // propertyType == Object
+ int idx = d->property.coreIndex();
+ Q_ASSERT(idx != -1);
+
+ void *a[1];
+ a[0] = (void *)&obj;
+ d->property.object()->qt_metacall(QMetaObject::WriteProperty,
+ idx, a);
+
+ } else if (d->property.propertyCategory() == QmlMetaProperty::Normal) {
+ QVariant value = this->value();
+ d->property.write(value);
+ }
+
+ d->updating = false;
+ } else {
+ qmlInfo(d->property.object()) << "Binding loop detected for property" << d->property.name();
+ }
+}
+
+void QmlBindableValue::valueChanged()
+{
+ update();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlbindablevalue.h b/src/declarative/qml/qmlbindablevalue.h
new file mode 100644
index 0000000..c4ef64a
--- /dev/null
+++ b/src/declarative/qml/qmlbindablevalue.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBINDABLEVALUE_H
+#define QMLBINDABLEVALUE_H
+
+#include <QObject>
+#include <qfxglobal.h>
+#include <qml.h>
+#include <qmlpropertyvaluesource.h>
+#include <QtDeclarative/qmlexpression.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlExpression;
+class QmlContext;
+class QmlBindableValuePrivate;
+class Q_DECLARATIVE_EXPORT QmlBindableValue : public QmlPropertyValueSource,
+ public QmlExpression
+{
+Q_OBJECT
+public:
+ QmlBindableValue(QObject *parent);
+ QmlBindableValue(const QString &, QObject *, bool = true, QObject *parent=0);
+ QmlBindableValue(void *, QmlRefCount *, QObject *, QObject *parent);
+ ~QmlBindableValue();
+
+ virtual void setTarget(const QmlMetaProperty &);
+ QmlMetaProperty property() const;
+
+ Q_CLASSINFO("DefaultProperty", "expression");
+ Q_PROPERTY(QString expression READ expression WRITE setExpression);
+ virtual void setExpression(const QString &);
+
+ void init();
+
+private Q_SLOTS:
+ void update();
+
+protected:
+ virtual void valueChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QmlBindableValue)
+};
+QML_DECLARE_TYPE(QmlBindableValue);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QMLBINDABLEVALUE_H
diff --git a/src/declarative/qml/qmlbindablevalue_p.h b/src/declarative/qml/qmlbindablevalue_p.h
new file mode 100644
index 0000000..d9af0ef
--- /dev/null
+++ b/src/declarative/qml/qmlbindablevalue_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBINDABLEVALUE_P_H
+#define QMLBINDABLEVALUE_P_H
+
+#include <private/qobject_p.h>
+#include <qmlbindablevalue.h>
+#include <qmlmetaproperty.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlBindableValuePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlBindableValue);
+public:
+ QmlBindableValuePrivate();
+
+ bool inited;
+ bool updating;
+ QmlMetaProperty property;
+
+ QmlBindableValue **mePtr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLBINDABLEVALUE_P_H
diff --git a/src/declarative/qml/qmlboundsignal.cpp b/src/declarative/qml/qmlboundsignal.cpp
new file mode 100644
index 0000000..5815dc6
--- /dev/null
+++ b/src/declarative/qml/qmlboundsignal.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlboundsignal_p.h"
+#include "private/qmetaobjectbuilder_p.h"
+#include "private/qmlengine_p.h"
+#include "private/qmlcontext_p.h"
+#include <qfxglobal.h>
+#include <qmlmetatype.h>
+#include <qml.h>
+#include <qmlcontext.h>
+
+QT_BEGIN_NAMESPACE
+
+int QmlBoundSignal::evaluateIdx = -1;
+QmlBoundSignal::QmlBoundSignal(QmlContext *ctxt, const QString &val, QObject *me, int idx, QObject *parent)
+: QmlExpressionObject(ctxt, val, me, false), _idx(idx)
+{
+ // A cached evaluation of the QmlExpressionObject::value() slot index.
+ //
+ // This is thread safe. Although it may be updated by two threads, they
+ // will both set it to the same value - so the worst thing that can happen
+ // is that they both do the work to figure it out. Boo hoo.
+ if (evaluateIdx == -1) evaluateIdx = QmlExpressionObject::staticMetaObject.indexOfMethod("value()");
+
+ setTrackChange(false);
+ QFx_setParent_noEvent(this, parent);
+ QMetaObject::connect(me, _idx, this, evaluateIdx);
+}
+
+QmlBoundSignalProxy::QmlBoundSignalProxy(QmlContext *ctxt, const QString &val, QObject *me, int idx, QObject *parent)
+: QmlBoundSignal(ctxt, val, me, idx, parent)
+{
+ QMetaMethod signal = me->metaObject()->method(idx);
+
+ params = new QmlBoundSignalParameters(signal, this);
+
+ ctxt->d_func()->addDefaultObject(params, QmlContextPrivate::HighPriority);
+}
+
+int QmlBoundSignalProxy::qt_metacall(QMetaObject::Call c, int id, void **a)
+{
+ if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) {
+ params->setValues(a);
+ value();
+ params->clearValues();
+ return -1;
+ } else {
+ return QmlBoundSignal::qt_metacall(c, id, a);
+ }
+}
+
+#include <QDebug>
+QmlBoundSignalParameters::QmlBoundSignalParameters(const QMetaMethod &method,
+ QObject *parent)
+: QObject(parent), types(0), values(0)
+{
+ MetaObject *mo = new MetaObject(this);
+
+ // ### Optimize!
+ // ### Ensure only supported types are allowed, otherwise it might crash
+ QMetaObjectBuilder mob;
+ mob.setSuperClass(&QmlBoundSignalParameters::staticMetaObject);
+ mob.setClassName("QmlBoundSignalParameters");
+
+ QList<QByteArray> paramTypes = method.parameterTypes();
+ QList<QByteArray> paramNames = method.parameterNames();
+ types = new int[paramTypes.count()];
+ for (int ii = 0; ii < paramTypes.count(); ++ii) {
+ const QByteArray &type = paramTypes.at(ii);
+ const QByteArray &name = paramNames.at(ii);
+
+ if (name.isEmpty() || type.isEmpty()) {
+ types[ii] = 0;
+ continue;
+ }
+
+ QVariant::Type t = (QVariant::Type)QMetaType::type(type.constData());
+ if (QmlMetaType::isObject(t)) {
+ types[ii] = QMetaType::QObjectStar;
+ QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
+ prop.setWritable(false);
+ } else {
+ types[ii] = t;
+ QMetaPropertyBuilder prop = mob.addProperty(name, type);
+ prop.setWritable(false);
+ }
+ }
+ myMetaObject = mob.toMetaObject();
+ *static_cast<QMetaObject *>(mo) = *myMetaObject;
+
+ d_ptr->metaObject = mo;
+}
+
+QmlBoundSignalParameters::~QmlBoundSignalParameters()
+{
+ delete [] types;
+ qFree(myMetaObject);
+}
+
+void QmlBoundSignalParameters::setValues(void **v)
+{
+ values = v;
+}
+
+void QmlBoundSignalParameters::clearValues()
+{
+ values = 0;
+}
+
+int QmlBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if (c == QMetaObject::ReadProperty && id >= 1) {
+ QmlMetaType::copy(types[id - 1], a[0], values[id]);
+ return -1;
+ } else {
+ return qt_metacall(c, id, a);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlboundsignal_p.h b/src/declarative/qml/qmlboundsignal_p.h
new file mode 100644
index 0000000..e84f0c1
--- /dev/null
+++ b/src/declarative/qml/qmlboundsignal_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBOUNDSIGNAL_P_H
+#define QMLBOUNDSIGNAL_P_H
+
+#include <qmlexpression.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+class QmlBoundSignal : public QmlExpressionObject
+{
+Q_OBJECT
+public:
+ QmlBoundSignal(QmlContext *, const QString &, QObject *me, int idx, QObject *parent);
+
+ int index() const { return _idx; }
+protected:
+ static int evaluateIdx;
+private:
+ int _idx;
+};
+
+class QmlBoundSignalParameters : public QObject
+{
+Q_OBJECT
+public:
+ QmlBoundSignalParameters(const QMetaMethod &, QObject * = 0);
+ ~QmlBoundSignalParameters();
+
+ void setValues(void **);
+ void clearValues();
+
+private:
+ friend class MetaObject;
+ int metaCall(QMetaObject::Call, int _id, void **);
+ struct MetaObject : public QAbstractDynamicMetaObject {
+ MetaObject(QmlBoundSignalParameters *b)
+ : parent(b) {}
+
+ int metaCall(QMetaObject::Call c, int id, void **a) {
+ return parent->metaCall(c, id, a);
+ }
+ QmlBoundSignalParameters *parent;
+ };
+
+ int *types;
+ void **values;
+ QMetaObject *myMetaObject;
+};
+
+class QmlBoundSignalProxy : public QmlBoundSignal
+{
+public:
+ QmlBoundSignalProxy(QmlContext *, const QString &, QObject *me, int idx, QObject *parent);
+
+protected:
+ virtual int qt_metacall(QMetaObject::Call c, int id, void **a);
+private:
+ QmlBoundSignalParameters *params;
+};
+
+
+#endif // QMLBOUNDSIGNAL_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlclassfactory.cpp b/src/declarative/qml/qmlclassfactory.cpp
new file mode 100644
index 0000000..7e5b929
--- /dev/null
+++ b/src/declarative/qml/qmlclassfactory.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlclassfactory_p.h"
+
+QmlClassFactory::~QmlClassFactory()
+{
+}
+
diff --git a/src/declarative/qml/qmlclassfactory_p.h b/src/declarative/qml/qmlclassfactory_p.h
new file mode 100644
index 0000000..e3e71c9
--- /dev/null
+++ b/src/declarative/qml/qmlclassfactory_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCLASSFACTORY_P_H
+#define QMLCLASSFACTORY_P_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QByteArray;
+class QUrl;
+class QmlComponent;
+
+class QmlClassFactory
+{
+public:
+ virtual ~QmlClassFactory();
+ virtual QmlComponent *create(const QByteArray &, const QUrl& baseUrl, QmlEngine*) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCLASSFACTORY_P_H
diff --git a/src/declarative/qml/qmlcompiledcomponent.cpp b/src/declarative/qml/qmlcompiledcomponent.cpp
new file mode 100644
index 0000000..bea736a
--- /dev/null
+++ b/src/declarative/qml/qmlcompiledcomponent.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcompiledcomponent_p.h"
+#include "qmlparser_p.h"
+#include <QtCore/qdebug.h>
+#include <QmlComponent>
+using namespace QmlParser;
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP);
+
+QmlCompiledComponent::QmlCompiledComponent()
+: dumpStatus(NoDump)
+{
+}
+
+QmlCompiledComponent::~QmlCompiledComponent()
+{
+ for (int ii = 0; ii < synthesizedMetaObjects.count(); ++ii)
+ qFree(synthesizedMetaObjects.at(ii));
+}
+
+
+void QmlCompiledComponent::dumpInstructions()
+{
+ if (!compilerDump())
+ return;
+
+ if (!name.isEmpty())
+ qWarning() << name;
+ qWarning() << "Index\tLine\tOperation\t\tData1\tData2\t\tComments";
+ qWarning() << "-------------------------------------------------------------------------------";
+ for (int ii = 0; ii < bytecode.count(); ++ii) {
+ dump(&bytecode[ii], ii);
+ }
+ qWarning() << "-------------------------------------------------------------------------------";
+}
+
+void QmlCompiledComponent::dumpPre()
+{
+ if (!(dumpStatus & DumpPre)) {
+ dumpInstructions();
+ dumpStatus = (DumpStatus)(dumpStatus | DumpPre);
+ }
+}
+
+void QmlCompiledComponent::dumpPost()
+{
+ if (!(dumpStatus & DumpPost)) {
+ dumpInstructions();
+ dumpStatus = (DumpStatus)(dumpStatus | DumpPost);
+ }
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiledcomponent_p.h b/src/declarative/qml/qmlcompiledcomponent_p.h
new file mode 100644
index 0000000..c5e1226
--- /dev/null
+++ b/src/declarative/qml/qmlcompiledcomponent_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPILEDCOMPONENT_P_H
+#define QMLCOMPILEDCOMPONENT_P_H
+
+#include <qml.h>
+#include <private/qmlinstruction_p.h>
+#include <private/qmlcompiler_p.h>
+#include <private/qmlrefcount_p.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+namespace QmlParser {
+ class Property;
+ class Object;
+ class Value;
+};
+
+class QmlCompiledComponent : public QmlRefCount, public QmlCompiledData
+{
+public:
+ QmlCompiledComponent();
+ ~QmlCompiledComponent();
+
+ void dumpPre();
+ void dumpPost();
+
+private:
+ enum DumpStatus { NoDump = 0x00, DumpPre = 0x01, DumpPost = 0x02 } dumpStatus;
+ void dumpInstructions();
+ void dump(QmlInstruction *, int idx = -1);
+ friend class QmlCompiler;
+ friend class QmlDomDocument;
+};
+
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QMLCOMPILEDCOMPONENT_P_H
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
new file mode 100644
index 0000000..a703ec3
--- /dev/null
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -0,0 +1,1512 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qmlcompiler_p.h"
+#include <qfxperf.h>
+#include "qmlparser_p.h"
+#include "private/qmlscriptparser_p.h"
+#include <qmlpropertyvaluesource.h>
+#include <qmlcomponent.h>
+#include "private/qmetaobjectbuilder_p.h"
+#include <qmlbasicscript.h>
+#include <QColor>
+#include <QDebug>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <private/qmlcompiledcomponent_p.h>
+#include <private/qmlstringconverters_p.h>
+#include <private/qmlengine_p.h>
+#include <qmlengine.h>
+#include <qmlcontext.h>
+#include <qmlmetatype.h>
+#include <QtCore/qdebug.h>
+#include "private/qmlcustomparser_p_p.h"
+#include <private/qmlcontext_p.h>
+#include <private/qmlcomponent_p.h>
+
+#include "qmlscriptparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlParser;
+
+int QmlCompiledData::indexForString(const QString &data)
+{
+ int idx = primitives.indexOf(data);
+ if (idx == -1) {
+ idx = primitives.count();
+ primitives << data;
+ }
+ return idx;
+}
+
+int QmlCompiledData::indexForByteArray(const QByteArray &data)
+{
+ int idx = datas.indexOf(data);
+ if (idx == -1) {
+ idx = datas.count();
+ datas << data;
+ }
+ return idx;
+}
+
+int QmlCompiledData::indexForFloat(float *data, int count)
+{
+ Q_ASSERT(count > 0);
+
+ for (int ii = 0; ii <= floatData.count() - count; ++ii) {
+ bool found = true;
+ for (int jj = 0; jj < count; ++jj) {
+ if (floatData.at(ii + jj) != data[jj]) {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ return ii;
+ }
+
+ int idx = floatData.count();
+ for (int ii = 0; ii < count; ++ii)
+ floatData << data[ii];
+
+ return idx;
+}
+
+int QmlCompiledData::indexForInt(int *data, int count)
+{
+ Q_ASSERT(count > 0);
+
+ for (int ii = 0; ii <= intData.count() - count; ++ii) {
+ bool found = true;
+ for (int jj = 0; jj < count; ++jj) {
+ if (intData.at(ii + jj) != data[jj]) {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ return ii;
+ }
+
+ int idx = intData.count();
+ for (int ii = 0; ii < count; ++ii)
+ intData << data[ii];
+
+ return idx;
+}
+
+int QmlCompiledData::indexForLocation(const QmlParser::Location &l)
+{
+ // ### FIXME
+ int rv = locations.count();
+ locations << l;
+ return rv;
+}
+
+int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l)
+{
+ // ### FIXME
+ int rv = locations.count();
+ locations << l.start << l.end;
+ return rv;
+}
+
+QmlCompiler::QmlCompiler()
+: exceptionLine(-1), exceptionColumn(-1), output(0)
+{
+}
+
+bool QmlCompiler::isError() const
+{
+ return exceptionLine != -1;
+}
+
+QList<QmlError> QmlCompiler::errors() const
+{
+ QList<QmlError> rv;
+
+ if(isError()) {
+ QmlError error;
+ error.setDescription(exceptionDescription);
+ error.setLine(exceptionLine);
+ error.setColumn(exceptionColumn);
+ rv << error;
+ }
+
+ return rv;
+}
+
+bool QmlCompiler::isValidId(const QString &val)
+{
+ if (val.isEmpty())
+ return false;
+
+ QChar u(QLatin1Char('_'));
+ for (int ii = 0; ii < val.count(); ++ii)
+ if (val.at(ii) != u &&
+ ((ii == 0 && !val.at(ii).isLetter()) ||
+ (ii != 0 && !val.at(ii).isLetterOrNumber())) )
+ return false;
+
+ return true;
+}
+
+/*!
+ Returns true if property name \a name refers to an attached property, false
+ otherwise.
+
+ Attached property names are those that start with a capital letter.
+*/
+bool QmlCompiler::isAttachedProperty(const QByteArray &name)
+{
+ return !name.isEmpty() && name.at(0) >= 'A' && name.at(0) <= 'Z';
+}
+
+QmlCompiler::StoreInstructionResult
+QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata,
+ QmlInstruction &instr,
+ const QMetaProperty &prop,
+ int coreIdx, int primitive,
+ const QString *string)
+{
+ if (!prop.isWritable())
+ return ReadOnly;
+ if (prop.isEnumType()) {
+ int value;
+ if (prop.isFlagType()) {
+ value = prop.enumerator().keysToValue(string->toLatin1().constData());
+ } else
+ value = prop.enumerator().keyToValue(string->toLatin1().constData());
+ if (value == -1)
+ return InvalidData;
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = coreIdx;
+ instr.storeInteger.value = value;
+ return Ok;
+ }
+ int type = prop.type();
+ switch(type) {
+ case -1:
+ instr.type = QmlInstruction::StoreVariant;
+ instr.storeString.propertyIndex = coreIdx;
+ if (primitive == -1)
+ primitive = cdata.indexForString(*string);
+ instr.storeString.value = primitive;
+ break;
+ break;
+ case QVariant::String:
+ {
+ instr.type = QmlInstruction::StoreString;
+ instr.storeString.propertyIndex = coreIdx;
+ if (primitive == -1)
+ primitive = cdata.indexForString(*string);
+ instr.storeString.value = primitive;
+ }
+ break;
+ case QVariant::UInt:
+ {
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = coreIdx;
+ bool ok;
+ int value = string->toUInt(&ok);
+ if (!ok)
+ return InvalidData;
+ instr.storeInteger.value = value;
+ }
+ break;
+ case QVariant::Int:
+ {
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = coreIdx;
+ bool ok;
+ int value = string->toInt(&ok);
+ if (!ok)
+ return InvalidData;
+ instr.storeInteger.value = value;
+ }
+ break;
+ case 135:
+ case QVariant::Double:
+ {
+ instr.type = QmlInstruction::StoreReal;
+ instr.storeReal.propertyIndex = coreIdx;
+ bool ok;
+ float value = string->toFloat(&ok);
+ if (!ok)
+ return InvalidData;
+ instr.storeReal.value = value;
+ }
+ break;
+ case QVariant::Color:
+ {
+ QColor c = QmlStringConverters::colorFromString(*string);
+ if (!c.isValid())
+ return InvalidData;
+ instr.type = QmlInstruction::StoreColor;
+ instr.storeColor.propertyIndex = coreIdx;
+ instr.storeColor.value = c.rgba();
+ }
+ break;
+ case QVariant::Date:
+ {
+ QDate d = QDate::fromString(*string, Qt::ISODate);
+ if (!d.isValid())
+ return InvalidData;
+ instr.type = QmlInstruction::StoreDate;
+ instr.storeDate.propertyIndex = coreIdx;
+ instr.storeDate.value = d.toJulianDay();
+ }
+ break;
+ case QVariant::Time:
+ {
+ QTime time = QTime::fromString(*string, Qt::ISODate);
+ if (!time.isValid())
+ return InvalidData;
+ int data[] = { time.hour(), time.minute(), time.second(), time.msec() };
+ int index = cdata.indexForInt(data, 4);
+ instr.type = QmlInstruction::StoreTime;
+ instr.storeTime.propertyIndex = coreIdx;
+ instr.storeTime.valueIndex = index;
+ }
+ break;
+ case QVariant::DateTime:
+ {
+ QDateTime dateTime = QDateTime::fromString(*string, Qt::ISODate);
+ if (!dateTime.isValid())
+ return InvalidData;
+ int data[] = { dateTime.date().toJulianDay(),
+ dateTime.time().hour(),
+ dateTime.time().minute(),
+ dateTime.time().second(),
+ dateTime.time().msec() };
+ int index = cdata.indexForInt(data, 5);
+ instr.type = QmlInstruction::StoreDateTime;
+ instr.storeDateTime.propertyIndex = coreIdx;
+ instr.storeDateTime.valueIndex = index;
+ }
+ break;
+ case QVariant::Point:
+ case QVariant::PointF:
+ {
+ bool ok;
+ QPointF point = QmlStringConverters::pointFFromString(*string, &ok);
+ if (!ok)
+ return InvalidData;
+ float data[] = { point.x(), point.y() };
+ int index = cdata.indexForFloat(data, 2);
+ if (type == QVariant::PointF)
+ instr.type = QmlInstruction::StorePointF;
+ else
+ instr.type = QmlInstruction::StorePoint;
+ instr.storeRealPair.propertyIndex = coreIdx;
+ instr.storeRealPair.valueIndex = index;
+ }
+ break;
+ case QVariant::Size:
+ case QVariant::SizeF:
+ {
+ bool ok;
+ QSizeF size = QmlStringConverters::sizeFFromString(*string, &ok);
+ if (!ok)
+ return InvalidData;
+ float data[] = { size.width(), size.height() };
+ int index = cdata.indexForFloat(data, 2);
+ if (type == QVariant::SizeF)
+ instr.type = QmlInstruction::StoreSizeF;
+ else
+ instr.type = QmlInstruction::StoreSize;
+ instr.storeRealPair.propertyIndex = coreIdx;
+ instr.storeRealPair.valueIndex = index;
+ }
+ break;
+ case QVariant::Rect:
+ case QVariant::RectF:
+ {
+ bool ok;
+ QRectF rect = QmlStringConverters::rectFFromString(*string, &ok);
+ if (!ok)
+ return InvalidData;
+ float data[] = { rect.x(), rect.y(),
+ rect.width(), rect.height() };
+ int index = cdata.indexForFloat(data, 4);
+ if (type == QVariant::RectF)
+ instr.type = QmlInstruction::StoreRectF;
+ else
+ instr.type = QmlInstruction::StoreRect;
+ instr.storeRect.propertyIndex = coreIdx;
+ instr.storeRect.valueIndex = index;
+ }
+ break;
+ case QVariant::Bool:
+ {
+ bool ok;
+ bool b = QmlStringConverters::boolFromString(*string, &ok);
+ if (!ok)
+ return InvalidData;
+ instr.type = QmlInstruction::StoreBool;
+ instr.storeBool.propertyIndex = coreIdx;
+ instr.storeBool.value = b;
+ }
+ break;
+ default:
+ {
+ int t = prop.type();
+ if (t == QVariant::UserType)
+ t = prop.userType();
+ QmlMetaType::StringConverter converter =
+ QmlMetaType::customStringConverter(t);
+ if (converter) {
+ int index = cdata.customTypeData.count();
+ instr.type = QmlInstruction::AssignCustomType;
+ instr.assignCustomType.propertyIndex = coreIdx;
+ instr.assignCustomType.valueIndex = index;
+
+ QmlCompiledData::CustomTypeData data;
+ if (primitive == -1)
+ primitive = cdata.indexForString(*string);
+ data.index = primitive;
+ data.type = t;
+ cdata.customTypeData << data;
+ break;
+ }
+ }
+ return UnknownType;
+ break;
+ }
+ return Ok;
+}
+
+void QmlCompiler::reset(QmlCompiledComponent *cc, bool deleteMemory)
+{
+ cc->types.clear();
+ cc->primitives.clear();
+ cc->floatData.clear();
+ cc->intData.clear();
+ cc->customTypeData.clear();
+ cc->datas.clear();
+ if (deleteMemory) {
+ for (int ii = 0; ii < cc->synthesizedMetaObjects.count(); ++ii)
+ qFree(cc->synthesizedMetaObjects.at(ii));
+ }
+ cc->synthesizedMetaObjects.clear();
+ cc->bytecode.clear();
+}
+
+#define COMPILE_EXCEPTION2(token, desc) \
+ { \
+ exceptionLine = token->location.start.line; \
+ exceptionColumn = token->location.start.column; \
+ QDebug d(&exceptionDescription); \
+ d << desc; \
+ exceptionDescription = exceptionDescription.trimmed(); \
+ return false; \
+ }
+
+#define COMPILE_EXCEPTION(desc) \
+ { \
+ exceptionLine = obj->location.start.line; \
+ exceptionColumn = obj->location.start.column; \
+ QDebug d(&exceptionDescription); \
+ d << desc; \
+ exceptionDescription = exceptionDescription.trimmed(); \
+ return false; \
+ }
+
+#define COMPILE_CHECK(a) \
+ { \
+ if (!a) return false; \
+ }
+
+bool QmlCompiler::compile(QmlEngine *engine,
+ QmlCompositeTypeData *unit,
+ QmlCompiledComponent *out)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::Compile> pc;
+#endif
+ exceptionLine = -1;
+
+ Q_ASSERT(out);
+ reset(out, true);
+
+ output = out;
+
+ // Compile types
+ for (int ii = 0; ii < unit->types.count(); ++ii) {
+ QmlCompositeTypeData::TypeReference &tref = unit->types[ii];
+ QmlCompiledComponent::TypeReference ref;
+ if (tref.type)
+ ref.type = tref.type;
+ else if (tref.unit) {
+ ref.component = tref.unit->toComponent(engine);
+ ref.ref = tref.unit;
+ ref.ref->addref();
+ }
+ ref.className = unit->data.types().at(ii).toLatin1();
+ out->types << ref;
+ }
+
+ Object *root = unit->data.tree();
+ Q_ASSERT(root);
+
+ compileTree(root);
+
+ if (!isError()) {
+ out->dumpPre();
+ } else {
+ reset(out, true);
+ }
+
+ output = 0;
+ return !isError();
+}
+
+void QmlCompiler::compileTree(Object *tree)
+{
+ QmlInstruction init;
+ init.type = QmlInstruction::Init;
+ init.line = 0;
+ init.init.dataSize = 0;
+ init.init.bindingsSize = 0;
+ init.init.parserStatusSize = 0;
+ output->bytecode << init;
+
+ if (!compileObject(tree, 0)) // Compile failed
+ return;
+
+ if (tree->metatype)
+ static_cast<QMetaObject &>(output->root) = *tree->metaObject();
+ else
+ static_cast<QMetaObject &>(output->root) = *output->types.at(tree->type).metaObject();
+
+ QmlInstruction def;
+ init.line = 0;
+ def.type = QmlInstruction::SetDefault;
+ output->bytecode << def;
+
+ optimizeExpressions(0, output->bytecode.count() - 1, 0);
+}
+
+bool QmlCompiler::compileObject(Object *obj, int ctxt)
+{
+ if (obj->type != -1)
+ obj->metatype = output->types.at(obj->type).metaObject();
+
+ if (output->types.at(obj->type).className == "Component") {
+ COMPILE_CHECK(compileComponent(obj, ctxt));
+ return true;
+ }
+
+ ctxt = 0;
+
+ int createInstrIdx = output->bytecode.count();
+ // Create the object
+ QmlInstruction create;
+ create.type = QmlInstruction::CreateObject;
+ create.line = obj->location.start.line;
+ create.create.data = -1;
+ create.create.type = obj->type;
+ output->bytecode << create;
+
+ COMPILE_CHECK(compileDynamicMeta(obj));
+
+ if (obj->type != -1) {
+ if (output->types.at(obj->type).component) {
+ QmlInstruction begin;
+ begin.type = QmlInstruction::TryBeginObject;
+ begin.line = obj->location.start.line;
+ output->bytecode << begin;
+ } else {
+ int cast = QmlMetaType::qmlParserStatusCast(QmlMetaType::type(output->types.at(obj->type).className));
+ if (cast != -1) {
+ QmlInstruction begin;
+ begin.type = QmlInstruction::BeginObject;
+ begin.begin.castValue = cast;
+ begin.line = obj->location.start.line;
+ output->bytecode << begin;
+ }
+ }
+ }
+
+ bool isCustomParser = output->types.at(obj->type).type &&
+ output->types.at(obj->type).type->customParser() != 0;
+ QList<QmlCustomParserProperty> customProps;
+
+ foreach(Property *prop, obj->properties) {
+ if (prop->name.length() >= 3 && prop->name.startsWith("on") &&
+ ('A' <= prop->name.at(2) && 'Z' >= prop->name.at(2))) {
+ if (!isCustomParser) {
+ COMPILE_CHECK(compileSignal(prop, obj));
+ } else {
+ customProps << QmlCustomParserNodePrivate::fromProperty(prop);
+ }
+ } else {
+ if (!isCustomParser || (isCustomParser && testProperty(prop, obj))) {
+ COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ } else {
+ customProps << QmlCustomParserNodePrivate::fromProperty(prop);
+ }
+ }
+ }
+
+ if (obj->defaultProperty) {
+ if(!isCustomParser || (isCustomParser && testProperty(obj->defaultProperty, obj))) {
+ COMPILE_CHECK(compileProperty(obj->defaultProperty, obj, ctxt));
+ } else {
+ customProps << QmlCustomParserNodePrivate::fromProperty(obj->defaultProperty);
+ }
+ }
+
+ if (isCustomParser && !customProps.isEmpty()) {
+ // ### Check for failure
+ bool ok = false;
+ QmlCustomParser *cp = output->types.at(obj->type).type->customParser();
+ QByteArray customData = cp->compile(customProps, &ok);
+ if(!ok)
+ COMPILE_EXCEPTION("Failure compiling custom type");
+ if(!customData.isEmpty())
+ output->bytecode[createInstrIdx].create.data =
+ output->indexForByteArray(customData);
+ }
+
+ if (obj->type != -1) {
+ if (output->types.at(obj->type).component) {
+ QmlInstruction complete;
+ complete.type = QmlInstruction::TryCompleteObject;
+ complete.line = obj->location.start.line;
+ output->bytecode << complete;
+ } else {
+ int cast = QmlMetaType::qmlParserStatusCast(QmlMetaType::type(output->types.at(obj->type).className));
+ if (cast != -1) {
+ QmlInstruction complete;
+ complete.type = QmlInstruction::CompleteObject;
+ complete.complete.castValue = cast;
+ complete.line = obj->location.start.line;
+ output->bytecode << complete;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileComponent(Object *obj, int ctxt)
+{
+ Property *idProp = 0;
+ if (obj->properties.count() > 1 ||
+ (obj->properties.count() == 1 && obj->properties.begin().key() != "id"))
+ COMPILE_EXCEPTION("Invalid component specification");
+ if (obj->defaultProperty &&
+ (obj->defaultProperty->value || obj->defaultProperty->values.count() > 1 ||
+ (obj->defaultProperty->values.count() == 1 && !obj->defaultProperty->values.first()->object)))
+ COMPILE_EXCEPTION("Invalid component body specification");
+ if (obj->properties.count())
+ idProp = *obj->properties.begin();
+ if (idProp && (idProp->value || idProp->values.count() > 1))
+ COMPILE_EXCEPTION("Invalid component id specification");
+
+ Object *root = 0;
+ if (obj->defaultProperty && obj->defaultProperty->values.count())
+ root = obj->defaultProperty->values.first()->object;
+
+ if (!root)
+ COMPILE_EXCEPTION("Cannot create empty component specification");
+
+ COMPILE_CHECK(compileComponentFromRoot(root, ctxt));
+
+ if (idProp && idProp->values.count()) {
+ QString val = idProp->values.at(0)->primitive();
+ if (!isValidId(val))
+ COMPILE_EXCEPTION("Invalid id property value");
+
+ if (ids.contains(val))
+ COMPILE_EXCEPTION("id is not unique");
+ ids.insert(val);
+
+ int pref = output->indexForString(val);
+ QmlInstruction id;
+ id.type = QmlInstruction::SetId;
+ id.line = idProp->location.start.line;
+ id.setId.value = pref;
+ id.setId.save = -1;
+ output->bytecode << id;
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileComponentFromRoot(Object *obj, int ctxt)
+{
+ output->bytecode.push_back(QmlInstruction());
+ QmlInstruction &create = output->bytecode.last();
+ create.type = QmlInstruction::CreateComponent;
+ create.line = obj->location.start.line;
+ create.createComponent.endLine = obj->location.end.line;
+ int count = output->bytecode.count();
+
+ QmlInstruction init;
+ init.type = QmlInstruction::Init;
+ init.init.dataSize = 0;
+ init.init.bindingsSize = 0;
+ init.init.parserStatusSize = 0;
+ init.line = obj->location.start.line;
+ output->bytecode << init;
+
+ QSet<QString> oldIds = ids;
+ ids.clear();
+ if (obj)
+ COMPILE_CHECK(compileObject(obj, ctxt));
+ ids = oldIds;
+
+ create.createComponent.count = output->bytecode.count() - count;
+
+ int inc = optimizeExpressions(count, count - 1 + create.createComponent.count, count);
+ create.createComponent.count += inc;
+ return true;
+}
+
+
+bool QmlCompiler::compileFetchedObject(Object *obj, int ctxt)
+{
+ if (obj->defaultProperty)
+ COMPILE_CHECK(compileProperty(obj->defaultProperty, obj, ctxt));
+
+ foreach(Property *prop, obj->properties) {
+ if (prop->name.length() >= 3 && prop->name.startsWith("on") &&
+ ('A' <= prop->name.at(2) && 'Z' >= prop->name.at(2))) {
+ COMPILE_CHECK(compileSignal(prop, obj));
+ } else {
+ COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ }
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileSignal(Property *prop, Object *obj)
+{
+ if (prop->values.isEmpty() && !prop->value)
+ return true;
+
+ if (prop->value || prop->values.count() > 1)
+ COMPILE_EXCEPTION("Incorrectly specified signal");
+
+ if (prop->values.at(0)->object) {
+ int pr = output->indexForByteArray(prop->name);
+
+ bool rv = compileObject(prop->values.at(0)->object, 0);
+
+ if (rv) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignSignalObject;
+ assign.line = prop->values.at(0)->location.start.line;
+ assign.assignSignalObject.signal = pr;
+
+ output->bytecode << assign;
+
+ prop->values.at(0)->type = Value::SignalObject;
+ }
+
+ return rv;
+
+ } else {
+ QString script = prop->values.at(0)->value.asScript().trimmed();
+ if (script.isEmpty())
+ return true;
+
+ int idx = output->indexForString(script);
+ int pr = output->indexForByteArray(prop->name);
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignSignal;
+ assign.line = prop->values.at(0)->location.start.line;
+ assign.assignSignal.signal = pr;
+ assign.assignSignal.value = idx;
+
+ output->bytecode << assign;
+
+ prop->values.at(0)->type = Value::SignalExpression;
+ }
+
+ return true;
+}
+
+// Returns true if prop exists on obj, false otherwise
+bool QmlCompiler::testProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ if(isAttachedProperty(prop->name) || prop->name == "id")
+ return true;
+
+ const QMetaObject *mo = obj->metaObject();
+ if (mo) {
+ if (prop->isDefault) {
+ QMetaProperty p = QmlMetaType::defaultProperty(mo);
+ return p.name() != 0;
+ } else {
+ int idx = mo->indexOfProperty(prop->name.constData());
+ return idx != -1;
+ }
+ }
+
+ return false;
+}
+
+bool QmlCompiler::compileProperty(Property *prop, Object *obj, int ctxt)
+{
+ if (prop->values.isEmpty() && !prop->value)
+ return true;
+
+ // First we're going to need a reference to this property
+ const QMetaObject *mo = obj->metaObject();
+ if (mo && !isAttachedProperty(prop->name)) {
+ if (prop->isDefault) {
+ QMetaProperty p = QmlMetaType::defaultProperty(mo);
+ // XXX
+ // Currently we don't handle enums in the static analysis
+ // so we let them drop through to generateStoreInstruction()
+ if (p.name() && !p.isEnumType()) {
+ prop->index = mo->indexOfProperty(p.name());
+ prop->name = p.name();
+
+ int t = p.type();
+ if (t == QVariant::UserType)
+ t = p.userType();
+
+ prop->type = t;
+ }
+ } else {
+ prop->index = mo->indexOfProperty(prop->name.constData());
+ QMetaProperty p = mo->property(prop->index);
+ // XXX
+ // Currently we don't handle enums in the static analysis
+ // so we let them drop through to generateStoreInstruction()
+ if (p.name() && !p.isEnumType()) {
+ int t = p.type();
+ if (t == QVariant::UserType)
+ t = p.userType();
+
+ prop->type = t;
+ }
+ }
+ }
+
+ if (prop->name == "id") {
+
+ COMPILE_CHECK(compileIdProperty(prop, obj));
+
+ } else if (isAttachedProperty(prop->name)) {
+
+ COMPILE_CHECK(compileAttachedProperty(prop, obj, ctxt));
+
+ } else if (prop->value) {
+
+ COMPILE_CHECK(compileNestedProperty(prop, ctxt));
+
+ } else if (QmlMetaType::isQmlList(prop->type) ||
+ QmlMetaType::isList(prop->type)) {
+
+ COMPILE_CHECK(compileListProperty(prop, obj, ctxt));
+
+ } else {
+
+ COMPILE_CHECK(compilePropertyAssignment(prop, obj, ctxt));
+
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileIdProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ if (prop->value)
+ COMPILE_EXCEPTION("The 'id' property cannot be fetched");
+ if (prop->values.count() > 1)
+ COMPILE_EXCEPTION("The 'id' property cannot be multiset");
+
+ if (prop->values.count() == 1) {
+ if (prop->values.at(0)->object)
+ COMPILE_EXCEPTION("Cannot assign an object as an id");
+ QString val = prop->values.at(0)->primitive();
+ if (!isValidId(val))
+ COMPILE_EXCEPTION(val << "is not a valid id");
+ if (ids.contains(val))
+ COMPILE_EXCEPTION("id is not unique");
+ ids.insert(val);
+
+ int pref = output->indexForString(val);
+
+ if (prop->type == QVariant::String) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreString;
+ assign.storeString.propertyIndex = prop->index;
+ assign.storeString.value = pref;
+ assign.line = prop->values.at(0)->location.start.line;
+ output->bytecode << assign;
+
+ prop->values.at(0)->type = Value::Id;
+ } else {
+ prop->values.at(0)->type = Value::Literal;
+ }
+
+ QmlInstruction id;
+ id.type = QmlInstruction::SetId;
+ id.line = prop->values.at(0)->location.start.line;
+ id.setId.value = pref;
+ id.setId.save = -1;
+ output->bytecode << id;
+
+ obj->id = val.toLatin1();
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileAttachedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt)
+{
+ if (!prop->value)
+ COMPILE_EXCEPTION("Incorrect usage of an attached property");
+
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchAttached;
+ fetch.line = prop->location.start.line;
+ int id = QmlMetaType::attachedPropertiesFuncId(prop->name);
+ if (id == -1)
+ COMPILE_EXCEPTION("Non-existant attached property object" << prop->name);
+ fetch.fetchAttached.id = id;
+ output->bytecode << fetch;
+
+ COMPILE_CHECK(compileFetchedObject(prop->value, ctxt + 1));
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopFetchedObject;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+
+ return true;
+}
+
+bool QmlCompiler::compileNestedProperty(QmlParser::Property *prop,
+ int ctxt)
+{
+ if (prop->type != 0)
+ prop->value->metatype = QmlMetaType::metaObjectForType(prop->type);
+
+ QmlInstruction fetch;
+ if (prop->index != -1 &&
+ QmlMetaType::isObject(prop->value->metatype)) {
+ fetch.type = QmlInstruction::FetchObject;
+ fetch.fetch.property = prop->index;
+ fetch.fetch.isObject = true;
+ } else {
+ fetch.type = QmlInstruction::ResolveFetchObject;
+ fetch.fetch.property = output->indexForByteArray(prop->name);
+ }
+ fetch.line = prop->location.start.line;
+ output->bytecode << fetch;
+
+ COMPILE_CHECK(compileFetchedObject(prop->value, ctxt + 1));
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopFetchedObject;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+
+ return true;
+}
+
+bool QmlCompiler::compileListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt)
+{
+ int t = prop->type;
+ if (QmlMetaType::isQmlList(t)) {
+ QmlInstruction fetch;
+ fetch.line = prop->location.start.line;
+ fetch.type = QmlInstruction::FetchQmlList;
+ fetch.fetchQmlList.property = prop->index;
+ fetch.fetchQmlList.type = QmlMetaType::qmlListType(t);
+ output->bytecode << fetch;
+
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if (v->object) {
+ v->type = Value::CreatedObject;
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObjectList;
+ assign.line = prop->location.start.line;
+ assign.assignObject.property = output->indexForByteArray(prop->name);
+ assign.assignObject.castValue = 0;
+ output->bytecode << assign;
+ } else {
+ COMPILE_EXCEPTION("Cannot assign primitives to lists");
+ }
+ }
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopQList;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+ } else {
+ Q_ASSERT(QmlMetaType::isList(t));
+
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchQList;
+ fetch.line = prop->location.start.line;
+ fetch.fetch.property = prop->index;
+ output->bytecode << fetch;
+
+ bool assignedBinding = false;
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if (v->object) {
+ v->type = Value::CreatedObject;
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObjectList;
+ assign.line = v->location.start.line;
+ assign.assignObject.property = output->indexForByteArray(prop->name);
+ assign.assignObject.castValue = 0;
+ output->bytecode << assign;
+ } else if (v->value.isScript()) {
+ if (assignedBinding)
+ COMPILE_EXCEPTION("Can only assign one binding to lists");
+
+ compileBinding(v->value.asScript(), prop, ctxt,
+ obj->metaObject(), v->location.start.line);
+ v->type = Value::PropertyBinding;
+ } else {
+ COMPILE_EXCEPTION("Cannot assign primitives to lists");
+ }
+ }
+
+ QmlInstruction pop;
+ pop.line = prop->location.start.line;
+ pop.type = QmlInstruction::PopQList;
+ output->bytecode << pop;
+ }
+ return true;
+}
+
+bool QmlCompiler::compilePropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt)
+{
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if (v->object) {
+
+ COMPILE_CHECK(compilePropertyObjectAssignment(prop, obj, v, ctxt));
+
+ } else {
+
+ COMPILE_CHECK(compilePropertyLiteralAssignment(prop, obj, v, ctxt));
+
+ }
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compilePropertyObjectAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ int ctxt)
+{
+ if (v->object->type != -1)
+ v->object->metatype = output->types.at(v->object->type).metaObject();
+
+ if (v->object->metaObject()) {
+
+ const QMetaObject *propmo =
+ QmlMetaType::rawMetaObjectForType(prop->type);
+
+ bool isPropertyValue = false;
+ bool isAssignable = false;
+
+ if (propmo) {
+ // We want to raw metaObject here as the raw metaobject is the
+ // actual property type before we applied any extensions
+ const QMetaObject *c = v->object->metatype;
+ while(propmo && c) {
+ isPropertyValue = isPropertyValue || (c == &QmlPropertyValueSource::staticMetaObject);
+ isAssignable = isAssignable || (c == propmo);
+ c = c->superClass();
+ }
+ } else {
+ const QMetaObject *c = v->object->metatype;
+ while(!isPropertyValue && c) {
+ isPropertyValue = c == &QmlPropertyValueSource::staticMetaObject;
+ c = c->superClass();
+ }
+ }
+
+ if (!propmo && !isPropertyValue) {
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObject;
+ assign.line = v->object->location.start.line;
+ assign.assignObject.castValue = 0;
+ if (prop->isDefault)
+ assign.assignObject.property = -1;
+ else
+ assign.assignObject.property =
+ output->indexForByteArray(prop->name);
+ output->bytecode << assign;
+
+ v->type = Value::CreatedObject;
+ } else if (isAssignable) {
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreObject;
+ assign.line = v->object->location.start.line;
+ assign.storeObject.propertyIndex = prop->index;
+ // XXX - this cast may not be 0
+ assign.storeObject.cast = 0;
+ output->bytecode << assign;
+
+ v->type = Value::CreatedObject;
+ } else if (propmo == &QmlComponent::staticMetaObject) {
+
+ COMPILE_CHECK(compileComponentFromRoot(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreObject;
+ assign.line = v->object->location.start.line;
+ assign.storeObject.propertyIndex = prop->index;
+ // XXX - this cast may not be 0
+ assign.storeObject.cast = 0;
+ output->bytecode << assign;
+
+ v->type = Value::Component;
+ } else if (isPropertyValue) {
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+
+ if (prop->index != -1) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreValueSource;
+ assign.line = v->object->location.start.line;
+ assign.assignValueSource.property = prop->index;
+ output->bytecode << assign;
+ } else {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignValueSource;
+ assign.line = v->object->location.start.line;
+ assign.assignValueSource.property = output->indexForByteArray(prop->name);;
+ output->bytecode << assign;
+ }
+
+ v->type = Value::ValueSource;
+ } else {
+ COMPILE_EXCEPTION("Unassignable object");
+ }
+
+ } else {
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObject;
+ assign.line = v->object->location.start.line;
+ assign.assignObject.property = output->indexForByteArray(prop->name);
+ assign.assignObject.castValue = 0;
+ output->bytecode << assign;
+
+ v->type = Value::CreatedObject;
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ int ctxt)
+{
+ if (v->value.isScript()) {
+
+ compileBinding(v->value.asScript(), prop, ctxt, obj->metaObject(),
+ v->location.start.line);
+
+ v->type = Value::PropertyBinding;
+
+ } else {
+
+ QmlInstruction assign;
+ assign.line = v->location.start.line;
+
+ bool doassign = true;
+ if (prop->index != -1) {
+ QString value = v->primitive();
+ StoreInstructionResult r =
+ generateStoreInstruction(*output, assign, obj->metaObject()->property(prop->index), prop->index, -1, &value);
+
+ if (r == Ok) {
+ doassign = false;
+ } else if (r == InvalidData) {
+ //### we are restricted to a rather generic message here. If we can find a way to move
+ // the exception into generateStoreInstruction we could potentially have better messages.
+ // (the problem is that both compile and run exceptions can be generated, though)
+ COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive() << "to property" << obj->metaObject()->property(prop->index).name());
+ doassign = false;
+ } else if (r == ReadOnly) {
+ COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive() << "to the read-only property" << obj->metaObject()->property(prop->index).name());
+ } else {
+ doassign = true;
+ }
+ }
+
+ if (doassign) {
+ assign.type = QmlInstruction::AssignConstant;
+ if (prop->isDefault) {
+ assign.assignConstant.property = -1;
+ } else {
+ assign.assignConstant.property =
+ output->indexForByteArray(prop->name);
+ }
+ assign.assignConstant.constant =
+ output->indexForString(v->primitive());
+ }
+
+ output->bytecode << assign;
+
+ v->type = Value::Literal;
+ }
+ return true;
+}
+
+bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj)
+{
+ // ### FIXME - Check that there is only one default property etc.
+ if (obj->dynamicProperties.isEmpty() &&
+ obj->dynamicSignals.isEmpty() &&
+ obj->dynamicSlots.isEmpty())
+ return true;
+
+ QMetaObjectBuilder builder;
+ if (obj->metatype)
+ builder.setClassName(QByteArray(obj->metatype->className()) + "QML");
+
+ builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ if (p.isDefaultProperty)
+ builder.addClassInfo("DefaultProperty", p.name);
+
+ QByteArray type;
+ switch(p.type) {
+ case Object::DynamicProperty::Variant:
+ type = "QVariant";
+ break;
+ case Object::DynamicProperty::Int:
+ type = "int";
+ break;
+ case Object::DynamicProperty::Bool:
+ type = "bool";
+ break;
+ case Object::DynamicProperty::Real:
+ type = "double";
+ break;
+ case Object::DynamicProperty::String:
+ type = "QString";
+ break;
+ case Object::DynamicProperty::Color:
+ type = "QColor";
+ break;
+ case Object::DynamicProperty::Date:
+ type = "QDate";
+ break;
+ }
+
+ builder.addSignal(p.name + "Changed()");
+ builder.addProperty(p.name, type, ii);
+ }
+
+ for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
+ const Object::DynamicSignal &s = obj->dynamicSignals.at(ii);
+ builder.addSignal(s.name + "()");
+ }
+
+ int slotStart = obj->dynamicSlots.isEmpty()?-1:output->primitives.count();
+
+ for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
+ const Object::DynamicSlot &s = obj->dynamicSlots.at(ii);
+ builder.addSlot(s.name + "()");
+ output->primitives << s.body;
+ }
+
+ if (obj->metatype)
+ builder.setSuperClass(obj->metatype);
+
+ obj->extObjectData = builder.toMetaObject();
+ static_cast<QMetaObject &>(obj->extObject) = *obj->extObjectData;
+
+ output->synthesizedMetaObjects << obj->extObjectData;
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreMetaObject;
+ store.storeMeta.data = output->synthesizedMetaObjects.count() - 1;
+ store.storeMeta.slotData = slotStart;
+ store.line = obj->location.start.line;
+ output->bytecode << store;
+
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ if (p.defaultValue) {
+ p.defaultValue->name = p.name;
+ p.defaultValue->isDefault = false;
+ COMPILE_CHECK(compileProperty(p.defaultValue, obj, 0));
+ }
+
+ if (!p.onValueChanged.isEmpty()) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignSignal;
+ assign.line = obj->location.start.line;
+ assign.assignSignal.signal =
+ output->indexForByteArray(p.name + "Changed()");
+ assign.assignSignal.value =
+ output->indexForString(p.onValueChanged);
+ output->bytecode << assign;
+ }
+ }
+
+ return true;
+}
+
+void QmlCompiler::compileBinding(const QString &bind, QmlParser::Property *prop,
+ int ctxt, const QMetaObject *mo, qint64 line)
+{
+ QmlBasicScript bs;
+ bs.compile(bind.toLatin1());
+
+ int bref;
+ if (bs.isValid()) {
+ bref = output->indexForByteArray(QByteArray(bs.compileData(), bs.compileDataSize()));
+ } else {
+ bref = output->indexForString(bind);
+ }
+
+ QmlInstruction assign;
+ assign.assignBinding.context = ctxt;
+ assign.line = line;
+ if (prop->index != -1) {
+ if (bs.isValid())
+ assign.type = QmlInstruction::StoreCompiledBinding;
+ else
+ assign.type = QmlInstruction::StoreBinding;
+
+ assign.assignBinding.property = prop->index;
+ assign.assignBinding.value = bref;
+ assign.assignBinding.category = QmlMetaProperty::Unknown;
+ if (mo) {
+ //XXX we should generate an exception if the property is read-only
+ QMetaProperty mp = mo->property(assign.assignBinding.property);
+ assign.assignBinding.category = QmlMetaProperty::propertyCategory(mp);
+ }
+ } else {
+ if (bs.isValid())
+ assign.type = QmlInstruction::AssignCompiledBinding;
+ else
+ assign.type = QmlInstruction::AssignBinding;
+ assign.assignBinding.property = output->indexForByteArray(prop->name);
+ assign.assignBinding.value = bref;
+ assign.assignBinding.category = QmlMetaProperty::Unknown;
+ }
+ output->bytecode << assign;
+}
+
+int QmlCompiler::optimizeExpressions(int start, int end, int patch)
+{
+ QHash<QString, int> ids;
+ int saveCount = 0;
+ int newInstrs = 0;
+ int bindingsCount = 0;
+ int parserStatusCount = 0;
+
+ for (int ii = start; ii <= end; ++ii) {
+ const QmlInstruction &instr = output->bytecode.at(ii);
+
+ if (instr.type == QmlInstruction::CreateComponent) {
+ ii += instr.createComponent.count - 1;
+ continue;
+ }
+
+ if (instr.type == QmlInstruction::SetId) {
+ QString id = output->primitives.at(instr.setId.value);
+ ids.insert(id, ii);
+ }
+ }
+
+ for (int ii = start; ii <= end; ++ii) {
+ const QmlInstruction &instr = output->bytecode.at(ii);
+
+ if (instr.type == QmlInstruction::CreateComponent) {
+ ii += instr.createComponent.count - 1;
+ continue;
+ }
+
+ if (instr.type == QmlInstruction::AssignBinding ||
+ instr.type == QmlInstruction::AssignCompiledBinding ||
+ instr.type == QmlInstruction::StoreBinding ||
+ instr.type == QmlInstruction::StoreCompiledBinding) {
+ ++bindingsCount;
+ } else if (instr.type == QmlInstruction::TryBeginObject ||
+ instr.type == QmlInstruction::BeginObject) {
+ ++parserStatusCount;
+ }
+
+
+ if (instr.type == QmlInstruction::StoreCompiledBinding) {
+ QmlBasicScript s(output->datas.at(instr.assignBinding.value).constData());
+
+ if (s.isSingleLoad()) {
+ QString slt = QLatin1String(s.singleLoadTarget());
+ if (!slt.at(0).isUpper())
+ continue;
+
+ if (ids.contains(slt) &&
+ instr.assignBinding.category == QmlMetaProperty::Object) {
+ int id = ids[slt];
+ int saveId = -1;
+
+ if (output->bytecode.at(id).setId.save != -1) {
+ saveId = output->bytecode.at(id).setId.save;
+ } else {
+ output->bytecode[id].setId.save = saveCount;
+ saveId = saveCount;
+ ++saveCount;
+ }
+
+ int prop = instr.assignBinding.property;
+
+ QmlInstruction &rwinstr = output->bytecode[ii];
+ rwinstr.type = QmlInstruction::PushProperty;
+ rwinstr.pushProperty.property = prop;
+
+ QmlInstruction instr;
+ instr.type = QmlInstruction::AssignStackObject;
+ instr.line = 0;
+ instr.assignStackObject.property = newInstrs;
+ instr.assignStackObject.object = saveId;
+ output->bytecode << instr;
+ ++newInstrs;
+ }
+ }
+ }
+ }
+
+ output->bytecode[patch].init.dataSize = saveCount;
+ output->bytecode[patch].init.bindingsSize = bindingsCount;
+ output->bytecode[patch].init.parserStatusSize = parserStatusCount;;
+
+ return newInstrs;
+}
+
+QmlCompiledData::QmlCompiledData()
+{
+}
+
+QmlCompiledData::QmlCompiledData(const QmlCompiledData &other)
+{
+ *this = other;
+}
+
+QmlCompiledData::~QmlCompiledData()
+{
+ for (int ii = 0; ii < types.count(); ++ii) {
+ if (types.at(ii).ref)
+ types.at(ii).ref->release();
+ }
+}
+
+QmlCompiledData &QmlCompiledData::operator=(const QmlCompiledData &other)
+{
+ types = other.types;
+ root = other.root;
+ primitives = other.primitives;
+ floatData = other.floatData;
+ intData = other.intData;
+ customTypeData = other.customTypeData;
+ datas = other.datas;
+ synthesizedMetaObjects = other.synthesizedMetaObjects;
+ bytecode = other.bytecode;
+ return *this;
+}
+
+QObject *QmlCompiledData::TypeReference::createInstance(QmlContext *ctxt) const
+{
+ if (type) {
+ QObject *rv = type->create();
+ if (rv)
+ QmlEngine::setContextForObject(rv, ctxt);
+ return rv;
+ } else {
+ Q_ASSERT(component);
+ QObject *rv = component->create(ctxt);
+ QmlContext *ctxt = qmlContext(rv);
+ if(ctxt) {
+ static_cast<QmlContextPrivate *>(QObjectPrivate::get(ctxt))->typeName = className;
+ }
+ return rv;
+ }
+}
+
+const QMetaObject *QmlCompiledData::TypeReference::metaObject() const
+{
+ if (type) {
+ return type->metaObject();
+ } else {
+ Q_ASSERT(component);
+ return &static_cast<QmlComponentPrivate *>(QObjectPrivate::get(component))->cc->root;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
new file mode 100644
index 0000000..246dd70
--- /dev/null
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPILER_P_H
+#define QMLCOMPILER_P_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qset.h>
+#include <qml.h>
+#include <qmlerror.h>
+#include <private/qmlinstruction_p.h>
+#include <private/qmlcompositetypemanager_p.h>
+#include <private/qmlparser_p.h>
+
+class QStringList;
+
+QT_BEGIN_NAMESPACE
+class QmlEngine;
+class QmlComponent;
+class QmlCompiledComponent;
+class QmlContext;
+
+class QmlCompiledData
+{
+public:
+ QmlCompiledData();
+ QmlCompiledData(const QmlCompiledData &other);
+ QmlCompiledData &operator=(const QmlCompiledData &other);
+ virtual ~QmlCompiledData();
+
+ QByteArray name;
+ QUrl url;
+
+ struct TypeReference
+ {
+ TypeReference()
+ : type(0), component(0), ref(0) {}
+
+ QByteArray className;
+ QmlType *type;
+ QmlComponent *component;
+
+ QmlRefCount *ref;
+ QObject *createInstance(QmlContext *) const;
+ const QMetaObject *metaObject() const;
+ };
+ QList<TypeReference> types;
+ struct CustomTypeData
+ {
+ int index;
+ int type;
+ };
+ QAbstractDynamicMetaObject root;
+ QList<QString> primitives;
+ QList<float> floatData;
+ QList<int> intData;
+ QList<CustomTypeData> customTypeData;
+ QList<QByteArray> datas;
+ QList<QMetaObject *> synthesizedMetaObjects;
+ QList<QmlParser::Location> locations;
+ QList<QmlInstruction> bytecode;
+
+private:
+ friend class QmlCompiler;
+ int indexForString(const QString &);
+ int indexForByteArray(const QByteArray &);
+ int indexForFloat(float *, int);
+ int indexForInt(int *, int);
+ int indexForLocation(const QmlParser::Location &);
+ int indexForLocation(const QmlParser::LocationSpan &);
+};
+
+class Q_DECLARATIVE_EXPORT QmlCompiler
+{
+public:
+ QmlCompiler();
+
+ bool compile(QmlEngine *, QmlCompositeTypeData *, QmlCompiledComponent *);
+
+ bool isError() const;
+ QList<QmlError> errors() const;
+
+ static bool isValidId(const QString &);
+ static bool isAttachedProperty(const QByteArray &);
+
+ enum StoreInstructionResult { Ok, UnknownType, InvalidData, ReadOnly };
+ static StoreInstructionResult
+ generateStoreInstruction(QmlCompiledData &data,
+ QmlInstruction &instr,
+ const QMetaProperty &prop,
+ int index,
+ int primitive,
+ const QString *string);
+private:
+ void reset(QmlCompiledComponent *, bool);
+
+ void compileTree(QmlParser::Object *tree);
+ bool compileObject(QmlParser::Object *obj, int);
+ bool compileComponent(QmlParser::Object *obj, int);
+ bool compileComponentFromRoot(QmlParser::Object *obj, int);
+ bool compileFetchedObject(QmlParser::Object *obj, int);
+ bool compileSignal(QmlParser::Property *prop, QmlParser::Object *obj);
+ bool testProperty(QmlParser::Property *prop, QmlParser::Object *obj);
+ bool compileProperty(QmlParser::Property *prop, QmlParser::Object *obj, int);
+ bool compileIdProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj);
+ bool compileAttachedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt);
+ bool compileNestedProperty(QmlParser::Property *prop,
+ int ctxt);
+ bool compileListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt);
+ bool compilePropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt);
+ bool compilePropertyObjectAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ int ctxt);
+ bool compilePropertyLiteralAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ int ctxt);
+
+ bool compileDynamicMeta(QmlParser::Object *obj);
+ void compileBinding(const QString &, QmlParser::Property *prop,
+ int ctxt, const QMetaObject *, qint64);
+
+ int optimizeExpressions(int start, int end, int patch = -1);
+
+ QSet<QString> ids;
+ qint64 exceptionLine;
+ qint64 exceptionColumn;
+ QString exceptionDescription;
+ QmlCompiledData *output;
+};
+
+QT_END_NAMESPACE
+#endif // QMLCOMPILER_P_H
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
new file mode 100644
index 0000000..da8f26d
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -0,0 +1,549 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcomponent.h"
+#include "qmlcomponent_p.h"
+#include "private/qmlcontext_p.h"
+#include "private/qmlengine_p.h"
+#include "qmlvme_p.h"
+#include "qml.h"
+#include <QStack>
+#include <qfxperf.h>
+#include <QStringList>
+#include <qmlengine.h>
+#include <QFileInfo>
+#include <qmlbindablevalue.h>
+#include "qmlcompiledcomponent_p.h"
+#include <QtCore/qdebug.h>
+#include <QApplication>
+
+#include "qmlscriptparser_p.h"
+
+QT_BEGIN_NAMESPACE
+class QByteArray;
+
+/*!
+ \class QmlComponent
+ \brief The QmlComponent class encapsulates a QML component description.
+ \mainclass
+*/
+
+/*!
+ \qmlclass Component QmlComponent
+ \brief The Component element encapsulates a QML component description.
+
+ Components are reusable, encapsulated Qml element with a well-defined interface.
+ They are often defined in \l {components}{Component Files}.
+
+ The \e Component element allows defining components within a QML file.
+ This can be useful for reusing a small component within a single QML
+ file, or for defining a component that logically belongs with the
+ file containing it.
+
+ \qml
+Item {
+ Component {
+ id: RedSquare
+ Rect {
+ color: "red"
+ width: 10
+ height: 10
+ }
+ }
+ ComponentInstance { component: RedSquare }
+ ComponentInstance { component: RedSquare; x: 20 }
+}
+ \endqml
+*/
+QML_DEFINE_TYPE(QmlComponent,Component);
+
+/*!
+ \enum QmlComponent::Status
+
+ Specifies the loading status of the QmlComponent.
+
+ \value Null This QmlComponent has no data. Call loadUrl() or setData() to add QML content.
+ \value Ready This QmlComponent is ready and create() may be called.
+ \value Loading This QmlComponent is loading network data.
+ \value Error An error has occured. Calling errorDescription() to retrieve a description.
+*/
+
+void QmlComponentPrivate::typeDataReady()
+{
+ Q_Q(QmlComponent);
+
+ Q_ASSERT(typeData);
+
+ fromTypeData(typeData);
+ typeData = 0;
+
+ emit q->statusChanged(q->status());
+}
+
+void QmlComponentPrivate::fromTypeData(QmlCompositeTypeData *data)
+{
+ url = QUrl(data->url);
+ QmlCompiledComponent *c = data->toCompiledComponent(engine);
+
+ if (!c) {
+ Q_ASSERT(data->status == QmlCompositeTypeData::Error);
+
+ errors = data->errors;
+
+ } else {
+
+ cc = c;
+
+ }
+
+ data->release();
+}
+
+void QmlComponentPrivate::clear()
+{
+ if (typeData) {
+ typeData->remWaiter(this);
+ typeData->release();
+ typeData = 0;
+ }
+
+ if (cc) {
+ cc->release();
+ cc = 0;
+ }
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+}
+
+/*!
+ Destruct the QmlComponent.
+*/
+QmlComponent::~QmlComponent()
+{
+ Q_D(QmlComponent);
+ if (d->typeData) {
+ d->typeData->remWaiter(d);
+ d->typeData->release();
+ }
+ if (d->cc)
+ d->cc->release();
+
+ for(int ii = 0; ii < d->bindValues.count(); ++ii)
+ QmlEnginePrivate::clear(d->bindValues[ii]);
+ for(int ii = 0; ii < d->parserStatus.count(); ++ii)
+ QmlEnginePrivate::clear(d->parserStatus[ii]);
+}
+
+/*!
+ Returns the component's current \l{QmlComponent::Status} {status}.
+ */
+QmlComponent::Status QmlComponent::status() const
+{
+ Q_D(const QmlComponent);
+
+ if (d->typeData)
+ return Loading;
+ else if (!d->errors.isEmpty())
+ return Error;
+ else if (d->engine && d->cc)
+ return Ready;
+ else
+ return Null;
+}
+
+/*!
+ Returns true if the component is in the Null state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Null.
+*/
+bool QmlComponent::isNull() const
+{
+ return status() == Null;
+}
+
+/*!
+ Returns true if the component is in the Ready state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Ready.
+*/
+bool QmlComponent::isReady() const
+{
+ return status() == Ready;
+}
+
+/*!
+ Returns true if the component is in the Error state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Error.
+*/
+bool QmlComponent::isError() const
+{
+ return status() == Error;
+}
+
+/*!
+ Returns true if the component is in the Loading state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Loading.
+*/
+bool QmlComponent::isLoading() const
+{
+ return status() == Loading;
+}
+
+/*!
+ \fn void QmlComponent::statusChanged(QmlComponent::Status status)
+
+ Emitted whenever the component's status changes. \a status will be the
+ new status.
+*/
+
+/*!
+ Create a QmlComponent with no data and give it the specified
+ \a engine and \a parent. Set the data with setData().
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+}
+
+/*!
+ Create a QmlComponent from the given \a url and give it the
+ specified \a parent and \a engine.
+
+ \sa loadUrl()
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, const QUrl &url, QObject *parent)
+: QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ loadUrl(url);
+}
+
+/*!
+ Create a QmlComponent from the given QML \a data and give it the
+ specified \a parent and \a engine. If \a url is provided, it is used to set
+ the component name, and to provide a base path for items resolved
+ by this component.
+
+ \sa setData()
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, const QByteArray &data, const QUrl &url, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ setData(data,url);
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, QmlCompiledComponent *cc, int start, int count, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ d->cc = cc;
+ cc->addref();
+ d->start = start;
+ d->count = count;
+}
+
+/*!
+ Sets the QmlComponent to use the given QML \a data. If \a url
+ is provided, it is used to set the component name and to provide
+ a base path for items resolved by this component.
+*/
+void QmlComponent::setData(const QByteArray &data, const QUrl &url)
+{
+ Q_D(QmlComponent);
+
+ d->clear();
+
+ d->url = url;
+
+ QmlCompositeTypeData *typeData =
+ d->engine->d_func()->typeManager.getImmediate(data, url);
+
+ if (typeData->status == QmlCompositeTypeData::Waiting) {
+
+ d->typeData = typeData;
+ d->typeData->addWaiter(d);
+
+ } else {
+
+ d->fromTypeData(typeData);
+
+ }
+
+ emit statusChanged(status());
+}
+
+/*!
+ Load the QmlComponent from the provided \a url.
+*/
+void QmlComponent::loadUrl(const QUrl &url)
+{
+ Q_D(QmlComponent);
+
+ d->clear();
+
+ d->url = url;
+
+ QmlCompositeTypeData *data =
+ d->engine->d_func()->typeManager.get(url);
+
+ if (data->status == QmlCompositeTypeData::Waiting) {
+
+ d->typeData = data;
+ d->typeData->addWaiter(d);
+
+ } else {
+
+ d->fromTypeData(data);
+
+ }
+
+ emit statusChanged(status());
+}
+
+/*!
+ Return the list of errors that occured during the last compile or create
+ operation. An empty list is returned if isError() is not set.
+*/
+QList<QmlError> QmlComponent::errors() const
+{
+ Q_D(const QmlComponent);
+ if (isError())
+ return d->errors;
+ else
+ return QList<QmlError>();
+}
+
+/*!
+ Return the component URL. This is the URL passed to either the constructor,
+ or the loadUrl() or setData() methods.
+*/
+QUrl QmlComponent::url() const
+{
+ Q_D(const QmlComponent);
+ return d->url;
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QmlComponentPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ Create an object instance from this component. Returns 0 if creation
+ failed. \a context specifies the context within which to create the object
+ instance.
+
+ If \a context is 0 (the default), it will create the instance in the
+ engine' s \l {QmlEngine::rootContext()}{root context}.
+*/
+QObject *QmlComponent::create(QmlContext *context)
+{
+ Q_D(QmlComponent);
+
+ if (!context)
+ context = d->engine->rootContext();
+
+ if (context->engine() != d->engine) {
+ qWarning("QmlComponent::create(): Must create component in context from the same QmlEngine");
+ return 0;
+ }
+
+ QObject *rv = beginCreate(context);
+ completeCreate();
+ return rv;
+}
+
+/*!
+ This method provides more advanced control over component instance creation.
+ In general, programmers should use QmlComponent::create() to create a
+ component.
+
+ Create an object instance from this component. Returns 0 if creation
+ failed. \a context specifies the context within which to create the object
+ instance.
+
+ When QmlComponent constructs an instance, it occurs in three steps:
+ \list 1
+ \i The object hierarchy is created, and constant values are assigned.
+ \i Property bindings are evaluated for the the first time.
+ \i If applicable, QmlParserStatus::componentComplete() is called on objects.
+ \endlist
+ QmlComponent::beginCreate() differs from QmlComponent::create() in that it
+ only performs step 1. QmlComponent::completeCreate() must be called to
+ complete steps 2 and 3.
+
+ This breaking point is sometimes useful when using attached properties to
+ communicate information to an instantiated component, as it allows their
+ initial values to be configured before property bindings take effect.
+*/
+QObject *QmlComponent::beginCreate(QmlContext *context)
+{
+ Q_D(QmlComponent);
+
+ if (!context) {
+ qWarning("QmlComponent::beginCreate(): Cannot create a component in a null context");
+ return 0;
+ }
+
+ if (context->engine() != d->engine) {
+ qWarning("QmlComponent::beginCreate(): Must create component in context from the same QmlEngine");
+ return 0;
+ }
+
+ if (d->completePending) {
+ qWarning("QmlComponent: Cannot create new component instance before completing the previous");
+ return 0;
+ }
+
+ if (!isReady()) {
+ qWarning("QmlComponent: Component is not ready");
+ return 0;
+ }
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::CreateComponent> perf;
+#endif
+ if (!d->engine->d_func()->rootComponent)
+ d->engine->d_func()->rootComponent = this;
+
+ QmlContext *ctxt =
+ new QmlContext(context, 0);
+ static_cast<QmlContextPrivate*>(ctxt->d_ptr)->url = d->cc->url;
+ if(d->start != -1) {
+ // ### FIXME
+ static_cast<QmlContextPrivate*>(ctxt->d_ptr)->startLine = d->cc->bytecode.at(d->start - 1).line;
+ static_cast<QmlContextPrivate*>(ctxt->d_ptr)->endLine = d->cc->bytecode.at(d->start - 1).createComponent.endLine;
+ }
+ ctxt->activate();
+
+ QmlVME vme;
+ QObject *rv = vme.run(ctxt, d->cc, d->start, d->count);
+
+ if (vme.isError())
+ d->errors = vme.errors();
+
+ ctxt->deactivate();
+
+ if (rv) {
+ QFx_setParent_noEvent(ctxt, rv);
+ QmlEnginePrivate *ep = d->engine->d_func();
+ if (ep->rootComponent == this) {
+ ep->rootComponent = 0;
+
+ d->bindValues = ep->bindValues;
+ d->parserStatus = ep->parserStatus;
+ ep->bindValues.clear();
+ ep->parserStatus.clear();
+ d->completePending = true;
+ }
+ } else {
+ delete ctxt;
+ }
+
+ return rv;
+}
+
+/*!
+ This method provides more advanced control over component instance creation.
+ In general, programmers should use QmlComponent::create() to create a
+ component.
+
+ Complete a component creation begin with QmlComponent::beginCreate().
+*/
+void QmlComponent::completeCreate()
+{
+ Q_D(QmlComponent);
+ if (d->completePending) {
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindInit> bi;
+#endif
+ for (int ii = 0; ii < d->bindValues.count(); ++ii) {
+ QmlEnginePrivate::SimpleList<QmlBindableValue> bv =
+ d->bindValues.at(ii);
+ for (int jj = 0; jj < bv.count; ++jj) {
+ if(bv.at(jj))
+ bv.at(jj)->init();
+ }
+ QmlEnginePrivate::clear(bv);
+ }
+ }
+
+ for (int ii = 0; ii < d->parserStatus.count(); ++ii) {
+ QmlEnginePrivate::SimpleList<QmlParserStatus> ps =
+ d->parserStatus.at(ii);
+
+ for (int jj = 0; jj < ps.count; ++jj) {
+ QmlParserStatus *status = ps.at(jj);
+ if (status && status->d) {
+ status->d = 0;
+ status->componentComplete();
+ }
+ }
+ QmlEnginePrivate::clear(ps);
+ }
+
+ d->bindValues.clear();
+ d->parserStatus.clear();
+ d->completePending = false;
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h
new file mode 100644
index 0000000..90f7467
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPONENT_H
+#define QMLCOMPONENT_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlerror.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlCompiledComponent;
+class QByteArray;
+class QmlComponentPrivate;
+class QmlEngine;
+class Q_DECLARATIVE_EXPORT QmlComponent : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlComponent);
+
+public:
+ QmlComponent(QObject *parent = 0);
+ QmlComponent(QmlEngine *, QObject *parent=0);
+ QmlComponent(QmlEngine *, const QUrl &url, QObject *parent = 0);
+ QmlComponent(QmlEngine *, const QByteArray &data,
+ const QUrl &baseUrl=QUrl(), QObject *parent=0);
+ virtual ~QmlComponent();
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+
+ bool isNull() const;
+ bool isReady() const;
+ bool isError() const;
+ bool isLoading() const;
+
+ QList<QmlError> errors() const;
+
+ QUrl url() const;
+
+ virtual QObject *create(QmlContext *context = 0);
+ virtual QObject *beginCreate(QmlContext *);
+ virtual void completeCreate();
+
+ void loadUrl(const QUrl &url);
+ void setData(const QByteArray &, const QUrl &baseUrl = QUrl());
+
+Q_SIGNALS:
+ void statusChanged(QmlComponent::Status);
+
+protected:
+ QmlComponent(QmlComponentPrivate &dd, QObject* parent);
+
+private:
+ QmlComponent(QmlEngine *, QmlCompiledComponent *, int, int, QObject *parent);
+
+ friend class QmlVME;
+ friend struct QmlCompositeTypeData;
+};
+QML_DECLARE_TYPE(QmlComponent);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLCOMPONENT_H
diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h
new file mode 100644
index 0000000..4de47c6
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPONENT_P_H
+#define QMLCOMPONENT_P_H
+
+#include <QString>
+#include <QStringList>
+#include <QList>
+#include "private/qobject_p.h"
+#include "private/qmlengine_p.h"
+#include "private/qmlcompositetypemanager_p.h"
+#include <qmlerror.h>
+#include "qmlcomponent.h"
+class QmlComponent;
+class QmlEngine;
+class QmlCompiledComponent;
+#include "qml.h"
+
+
+QT_BEGIN_NAMESPACE
+
+class QmlComponentPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlComponent)
+
+public:
+ QmlComponentPrivate() : typeData(0), start(-1), count(-1), cc(0), completePending(false), engine(0) {}
+
+ QmlCompositeTypeData *typeData;
+ void typeDataReady();
+
+ void fromTypeData(QmlCompositeTypeData *data);
+
+ QList<QmlError> errors;
+ QUrl url;
+
+ int start;
+ int count;
+ QmlCompiledComponent *cc;
+
+ QList<QmlEnginePrivate::SimpleList<QmlBindableValue> > bindValues;
+ QList<QmlEnginePrivate::SimpleList<QmlParserStatus> > parserStatus;
+
+ bool completePending;
+
+ QmlEngine *engine;
+
+ void clear();
+};
+
+#endif // QMLCOMPONENT_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp
new file mode 100644
index 0000000..e1124a6
--- /dev/null
+++ b/src/declarative/qml/qmlcompositetypemanager.cpp
@@ -0,0 +1,365 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qmlcompositetypemanager_p.h>
+#include <private/qmlscriptparser_p.h>
+#include <private/qmlcompiledcomponent_p.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtNetwork/qnetworkreply.h>
+#include <private/qmlengine_p.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlcomponent_p.h>
+
+QmlCompositeTypeData::QmlCompositeTypeData()
+: status(Invalid), errorType(NoError), component(0), compiledComponent(0)
+{
+}
+
+QmlCompositeTypeData::~QmlCompositeTypeData()
+{
+ for (int ii = 0; ii < dependants.count(); ++ii)
+ dependants.at(ii)->release();
+
+ if (compiledComponent)
+ compiledComponent->release();
+
+ if (component)
+ delete component;
+}
+
+void QmlCompositeTypeData::addWaiter(QmlComponentPrivate *p)
+{
+ waiters << p;
+}
+
+void QmlCompositeTypeData::remWaiter(QmlComponentPrivate *p)
+{
+ waiters.removeAll(p);
+}
+
+QmlComponent *QmlCompositeTypeData::toComponent(QmlEngine *engine)
+{
+ if (!component) {
+
+ QmlCompiledComponent *cc = toCompiledComponent(engine);
+ if (cc) {
+ component = new QmlComponent(engine, cc, -1, -1, 0);
+ } else {
+ component = new QmlComponent(engine, 0);
+ }
+
+ }
+
+ return component;
+}
+
+QmlCompiledComponent *
+QmlCompositeTypeData::toCompiledComponent(QmlEngine *engine)
+{
+ if (status == Complete && !compiledComponent) {
+
+ compiledComponent = new QmlCompiledComponent;
+ compiledComponent->url = QUrl(url);
+ compiledComponent->name = url.toLatin1(); // ###
+
+ QmlCompiler compiler;
+ if (!compiler.compile(engine, this, compiledComponent)) {
+ status = Error;
+ errors = compiler.errors();
+ for(int ii = 0; ii < errors.count(); ++ii)
+ errors[ii].setUrl(url);
+ compiledComponent->release();
+ compiledComponent = 0;
+ }
+
+ // Data is no longer needed once we have a compiled component
+ data.clear();
+ }
+
+ if (compiledComponent)
+ compiledComponent->addref();
+
+ return compiledComponent;
+}
+
+QmlCompositeTypeData::TypeReference::TypeReference()
+: type(0), unit(0)
+{
+}
+
+QmlCompositeTypeManager::QmlCompositeTypeManager(QmlEngine *e)
+: engine(e)
+{
+}
+
+QmlCompositeTypeData *QmlCompositeTypeManager::get(const QUrl &url)
+{
+ QmlCompositeTypeData *unit = components.value(url.toString());
+
+ if (!unit) {
+ unit = new QmlCompositeTypeData;
+ unit->status = QmlCompositeTypeData::Waiting;
+ unit->url = url.toString();
+ components.insert(url.toString(), unit);
+
+ loadSource(unit);
+ }
+
+ unit->addref();
+ return unit;
+}
+
+QmlCompositeTypeData *
+QmlCompositeTypeManager::getImmediate(const QByteArray &data, const QUrl &url)
+{
+ QmlCompositeTypeData *unit = new QmlCompositeTypeData;
+ unit->status = QmlCompositeTypeData::Waiting;
+ unit->url = url.toString();
+ setData(unit, data, url);
+ return unit;
+}
+
+void QmlCompositeTypeManager::clearCache()
+{
+ for (Components::Iterator iter = components.begin(); iter != components.end();) {
+ if ((*iter)->status != QmlCompositeTypeData::Waiting) {
+ (*iter)->release();
+ iter = components.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+
+void QmlCompositeTypeManager::replyFinished()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+
+ QmlCompositeTypeData *unit = components.value(reply->url().toString());
+ Q_ASSERT(unit);
+
+ if (reply->error() != QNetworkReply::NoError) {
+
+ QString errorDescription;
+ // ### - Fill in error
+ errorDescription = QLatin1String("Network error for URL ") +
+ reply->url().toString();
+
+ unit->status = QmlCompositeTypeData::Error;
+ // ### FIXME
+ QmlError error;
+ error.setDescription(errorDescription);
+ unit->errorType = QmlCompositeTypeData::AccessError;
+ unit->errors << error;
+ doComplete(unit);
+
+ } else {
+ QByteArray data = reply->readAll();
+
+ setData(unit, data, reply->url());
+ }
+
+ reply->deleteLater();
+}
+
+void QmlCompositeTypeManager::loadSource(QmlCompositeTypeData *unit)
+{
+ QUrl url(unit->url);
+
+ if (url.scheme() == QLatin1String("file")) {
+
+ QFile file(url.toLocalFile());
+ if (file.open(QFile::ReadOnly)) {
+ QByteArray data = file.readAll();
+ setData(unit, data, url);
+ } else {
+ QString errorDescription;
+ // ### - Fill in error
+ errorDescription = QLatin1String("File error for URL ") + url.toString();
+ unit->status = QmlCompositeTypeData::Error;
+ // ### FIXME
+ QmlError error;
+ error.setDescription(errorDescription);
+ unit->errorType = QmlCompositeTypeData::AccessError;
+ unit->errors << error;
+ doComplete(unit);
+ }
+
+ } else {
+ QNetworkReply *reply =
+ engine->networkAccessManager()->get(QNetworkRequest(url));
+ QObject::connect(reply, SIGNAL(finished()),
+ this, SLOT(replyFinished()));
+ }
+}
+
+void QmlCompositeTypeManager::setData(QmlCompositeTypeData *unit,
+ const QByteArray &data,
+ const QUrl &url)
+{
+ if (!unit->data.parse(data, url)) {
+
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errorType = QmlCompositeTypeData::GeneralError;
+ unit->errors << unit->data.errors();
+ doComplete(unit);
+
+ } else {
+
+ engine->addNameSpacePaths(unit->data.nameSpacePaths());
+ compile(unit);
+
+ }
+}
+
+void QmlCompositeTypeManager::doComplete(QmlCompositeTypeData *unit)
+{
+ for (int ii = 0; ii < unit->dependants.count(); ++ii) {
+ checkComplete(unit->dependants.at(ii));
+ unit->dependants.at(ii)->release();
+ }
+ unit->dependants.clear();
+
+ while(!unit->waiters.isEmpty()) {
+ QmlComponentPrivate *p = unit->waiters.takeFirst();
+ p->typeDataReady();
+ }
+}
+
+void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit)
+{
+ if (unit->status != QmlCompositeTypeData::Waiting)
+ return;
+
+ int waiting = 0;
+ for (int ii = 0; ii < unit->types.count(); ++ii) {
+ QmlCompositeTypeData *u = unit->types.at(ii).unit;
+
+ if (!u)
+ continue;
+
+ if (u->status == QmlCompositeTypeData::Error) {
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errors = u->errors;
+ doComplete(unit);
+ return;
+ } else if (u->status == QmlCompositeTypeData::Waiting) {
+ waiting++;
+ }
+ }
+ if (!waiting) {
+ unit->status = QmlCompositeTypeData::Complete;
+ doComplete(unit);
+ }
+}
+
+void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
+{
+ QStringList typeNames = unit->data.types();
+
+ int waiting = 0;
+ for (int ii = 0; ii < typeNames.count(); ++ii) {
+ QByteArray type = typeNames.at(ii).toLatin1();
+
+ QmlCompositeTypeData::TypeReference ref;
+ if (type == QByteArray("Property") ||
+ type == QByteArray("Signal")) {
+ unit->types << ref;
+ continue;
+ }
+
+ ref.type = QmlMetaType::qmlType(type);
+ if (ref.type) {
+ unit->types << ref;
+ continue;
+ }
+
+ QUrl url = engine->componentUrl(QUrl(type + ".qml"), QUrl(unit->url));
+ QmlCompositeTypeData *urlUnit = components.value(url.toString());
+
+ if (!urlUnit) {
+ urlUnit = new QmlCompositeTypeData;
+ urlUnit->status = QmlCompositeTypeData::Waiting;
+ urlUnit->url = url.toString();
+ components.insert(url.toString(), urlUnit);
+
+ loadSource(urlUnit);
+ }
+
+ ref.unit = urlUnit;
+ switch(urlUnit->status) {
+ case QmlCompositeTypeData::Invalid:
+ case QmlCompositeTypeData::Error:
+ unit->status = QmlCompositeTypeData::Error;
+ {
+ QmlError error;
+ error.setUrl(unit->url);
+ error.setDescription("Type " + type + " unavailable");
+ unit->errors << error;
+ }
+ if (urlUnit->errorType != QmlCompositeTypeData::AccessError)
+ unit->errors << urlUnit->errors;
+ doComplete(unit);
+ return;
+
+ case QmlCompositeTypeData::Complete:
+ break;
+
+ case QmlCompositeTypeData::Waiting:
+ unit->addref();
+ ref.unit->dependants << unit;
+ waiting++;
+ break;
+ }
+
+ unit->types << ref;
+ }
+
+ if (waiting) {
+ unit->status = QmlCompositeTypeData::Waiting;
+ } else {
+ unit->status = QmlCompositeTypeData::Complete;
+ doComplete(unit);
+ }
+}
diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h
new file mode 100644
index 0000000..f03b2cb
--- /dev/null
+++ b/src/declarative/qml/qmlcompositetypemanager_p.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCOMPOSITETYPEMANAGER_P_H
+#define QMLCOMPOSITETYPEMANAGER_P_H
+
+#include <qglobal.h>
+#include <private/qmlscriptparser_p.h>
+#include <private/qmlrefcount_p.h>
+#include <qmlerror.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlCompiledComponent;
+class QmlComponentPrivate;
+class QmlComponent;
+class QmlDomDocument;
+struct QmlCompositeTypeData : public QmlRefCount
+{
+ QmlCompositeTypeData();
+ virtual ~QmlCompositeTypeData();
+
+ enum Status {
+ Invalid,
+ Complete,
+ Error,
+ Waiting
+ };
+ Status status;
+ enum ErrorType {
+ NoError,
+ AccessError,
+ GeneralError
+ };
+ ErrorType errorType;
+
+ QList<QmlError> errors;
+
+ QString url;
+ QList<QmlCompositeTypeData *> dependants;
+
+ // Return a QmlComponent if the QmlCompositeTypeData is not in the Waiting
+ // state. The QmlComponent is owned by the QmlCompositeTypeData, so a
+ // reference should be kept to keep the QmlComponent alive.
+ QmlComponent *toComponent(QmlEngine *);
+ // Return a QmlCompiledComponent if possible, or 0 if an error
+ // occurs
+ QmlCompiledComponent *toCompiledComponent(QmlEngine *);
+
+ struct TypeReference
+ {
+ TypeReference();
+
+ QmlType *type;
+ QmlCompositeTypeData *unit;
+ };
+
+ QList<TypeReference> types;
+
+ // Add or remove p as a waiter. When the QmlCompositeTypeData becomes
+ // ready, the QmlComponentPrivate::typeDataReady() method will be invoked on
+ // p. The waiter is automatically removed when the typeDataReady() method
+ // is invoked, so there is no need to call remWaiter() in this case.
+ void addWaiter(QmlComponentPrivate *p);
+ void remWaiter(QmlComponentPrivate *p);
+
+private:
+ friend class QmlCompositeTypeManager;
+ friend class QmlCompiler;
+ friend class QmlDomDocument;
+
+ QmlScriptParser data;
+ QList<QmlComponentPrivate *> waiters;
+ QmlComponent *component;
+ QmlCompiledComponent *compiledComponent;
+};
+
+class QmlCompositeTypeManager : public QObject
+{
+ Q_OBJECT
+public:
+ QmlCompositeTypeManager(QmlEngine *);
+
+ // Return a QmlCompositeTypeData for url. The QmlCompositeTypeData may be
+ // cached.
+ QmlCompositeTypeData *get(const QUrl &url);
+ // Return a QmlCompositeTypeData for data, with the provided base url. The
+ // QmlCompositeTypeData will not be cached.
+ QmlCompositeTypeData *getImmediate(const QByteArray &data, const QUrl &url);
+
+ // Clear cached types. Only types that aren't in the Waiting state will
+ // be cleared.
+ void clearCache();
+
+private Q_SLOTS:
+ void replyFinished();
+
+private:
+ void loadSource(QmlCompositeTypeData *);
+ void compile(QmlCompositeTypeData *);
+ void setData(QmlCompositeTypeData *, const QByteArray &, const QUrl &);
+
+ void doComplete(QmlCompositeTypeData *);
+ void checkComplete(QmlCompositeTypeData *);
+
+ QmlEngine *engine;
+ typedef QHash<QString, QmlCompositeTypeData *> Components;
+ Components components;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCOMPOSITETYPEMANAGER_P_H
+
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
new file mode 100644
index 0000000..91bf1c0
--- /dev/null
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -0,0 +1,500 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qmlcontext.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmlengine_p.h>
+#include <qmlengine.h>
+#include <qscriptengine.h>
+#include <QtCore/qvarlengtharray.h>
+
+#include <qdebug.h>
+
+// 6-bits
+#define MAXIMUM_DEFAULT_OBJECTS 63
+
+QT_BEGIN_NAMESPACE
+
+QmlContextPrivate::QmlContextPrivate()
+: parent(0), engine(0), notifyIndex(-1), highPriorityCount(0),
+ startLine(-1), endLine(-1)
+{
+}
+
+void QmlContextPrivate::dump()
+{
+ dump(0);
+}
+
+void QmlContextPrivate::dump(int depth)
+{
+ QByteArray ba(depth * 4, ' ');
+ if (parent)
+ parent->d_func()->dump(depth + 1);
+}
+
+void QmlContextPrivate::destroyed(QObject *obj)
+{
+ Q_Q(QmlContext);
+
+ defaultObjects.removeAll(obj);
+
+ QVariant variantObject = QVariant::fromValue(obj);
+ QVarLengthArray<int> notifies;
+ for (int ii = 0; ii < propertyValues.count(); ++ii) {
+ if (propertyValues.at(ii) == variantObject) {
+ propertyValues[ii] = QVariant();
+ notifies.append(ii);
+ }
+ }
+ for (int ii = 0; ii < notifies.count(); ++ii) {
+ QMetaObject::activate(q, notifies[ii] + notifyIndex, 0);
+ }
+}
+
+void QmlContextPrivate::init()
+{
+ Q_Q(QmlContext);
+
+ if (parent)
+ parent->d_func()->childContexts.insert(q);
+
+ //set scope chain
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+ QScriptValue scopeObj =
+ scriptEngine->newObject(engine->d_func()->contextClass, scriptEngine->newVariant(QVariant::fromValue((QObject*)q)));
+ if (!parent)
+ scopeChain.append(scriptEngine->globalObject());
+ else
+ scopeChain = parent->d_func()->scopeChain;
+ scopeChain.prepend(scopeObj);
+
+ contextData.context = q;
+}
+
+void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority)
+{
+ if (defaultObjects.count() >= (MAXIMUM_DEFAULT_OBJECTS - 1)) {
+ qWarning("QmlContext: Cannot have more than %d default objects on "
+ "one bind context.", MAXIMUM_DEFAULT_OBJECTS - 1);
+ return;
+ }
+
+ if (priority == HighPriority) {
+ defaultObjects.insert(highPriorityCount++, object);
+ } else {
+ defaultObjects.append(object);
+ }
+ QObject::connect(object, SIGNAL(destroyed(QObject*)),
+ q_ptr, SLOT(objectDestroyed(QObject*)));
+}
+
+
+/*!
+ \class QmlContext
+ \brief The QmlContext class defines a context within a QML engine.
+ \mainclass
+
+ Contexts allow data to be exposed to the QML components instantiated by the
+ QML engine.
+
+ Each QmlContext contains a set of properties, distinct from
+ its QObject properties, that allow data to be
+ explicitly bound to a context by name. The context properties are defined or
+ updated by calling QmlContext::setContextProperty(). The following example shows
+ a Qt model being bound to a context and then accessed from a QML file.
+
+ \code
+ QmlEngine engine;
+ QmlContext context(engine.rootContext());
+ context.setContextProperty("myModel", modelData);
+
+ QmlComponent component("ListView { model=myModel }");
+ component.create(&context);
+ \endcode
+
+ To simplify binding and maintaining larger data sets, QObject's can be
+ added to a QmlContext. These objects are known as the context's default
+ objects. In this case all the properties of the QObject are
+ made available by name in the context, as though they were all individually
+ added by calling QmlContext::setContextProperty(). Changes to the property's
+ values are detected through the property's notify signal. This method is
+ also slightly more faster than manually adding property values.
+
+ The following example has the same effect as the one above, but it is
+ achieved using a default object.
+
+ \code
+ class MyDataSet : ... {
+ ...
+ Q_PROPERTY(QAbstractItemModel *myModel READ model NOTIFY modelChanged);
+ ...
+ };
+
+ MyDataSet myDataSet;
+ QmlEngine engine;
+ QmlContext context(engine.rootContext());
+ context.addDefaultObject(&myDataSet);
+
+ QmlComponent component("ListView { model=myModel }");
+ component.create(&context);
+ \endcode
+
+ Each context may have up to 32 default objects, and objects added first take
+ precedence over those added later. All properties added explicitly by
+ QmlContext::setContextProperty() take precedence over default object properties.
+
+ Contexts are hierarchal, with the \l {QmlEngine::rootContext()}{root context}
+ being created by the QmlEngine. A component instantiated in a given context
+ has access to that context's data, as well as the data defined by its
+ ancestor contexts. Data values (including those added implicitly by the
+ default objects) in a context override those in ancestor contexts. Data
+ that should be available to all components instantiated by the QmlEngine
+ should be added to the \l {QmlEngine::rootContext()}{root context}.
+
+ In the following example,
+
+ \code
+ QmlEngine engine;
+ QmlContext context1(engine.rootContext());
+ QmlContext context2(&context1);
+ QmlContext context3(&context2);
+
+ context1.setContextProperty("a", 12);
+ context2.setContextProperty("b", 13);
+ context3.setContextProperty("a", 14);
+ context3.setContextProperty("c", 14);
+ \endcode
+
+ a QML component instantiated in context1 would have access to the "a" data,
+ a QML component instantiated in context2 would have access to the "a" and
+ "b" data, and a QML component instantiated in context3 would have access to
+ the "a", "b" and "c" data - although its "a" data would return 14, unlike
+ that in context1 or context2.
+*/
+
+/*! \internal */
+QmlContext::QmlContext(QmlEngine *e)
+: QObject(*(new QmlContextPrivate))
+{
+ Q_D(QmlContext);
+ d->engine = e;
+ d->init();
+}
+
+/*!
+ Create a new QmlContext with the given \a parentContext, and the
+ QObject \a parent.
+*/
+QmlContext::QmlContext(QmlContext *parentContext, QObject *parent)
+: QObject(*(new QmlContextPrivate), parent)
+{
+ Q_D(QmlContext);
+ d->parent = parentContext;
+ d->engine = parentContext->engine();
+ d->init();
+}
+
+/*!
+ Destroys the QmlContext.
+
+ Any expressions, or sub-contexts dependent on this context will be
+ invalidated, but not destroyed (unless they are parented to the QmlContext
+ object).
+ */
+QmlContext::~QmlContext()
+{
+ Q_D(QmlContext);
+ if (d->parent)
+ d->parent->d_func()->childContexts.remove(this);
+
+ for (QSet<QmlContext *>::ConstIterator iter = d->childContexts.begin();
+ iter != d->childContexts.end();
+ ++iter) {
+ (*iter)->d_func()->invalidateEngines();
+ (*iter)->d_func()->parent = 0;
+ }
+
+ for (QSet<QmlExpression *>::ConstIterator iter =
+ d->childExpressions.begin();
+ iter != d->childExpressions.end();
+ ++iter) {
+ (*iter)->d->ctxt = 0;
+ }
+
+ for (int ii = 0; ii < d->contextObjects.count(); ++ii) {
+ QObjectPrivate *p = QObjectPrivate::get(d->contextObjects.at(ii));
+ QmlSimpleDeclarativeData *data =
+ static_cast<QmlSimpleDeclarativeData *>(p->declarativeData);
+ if(data && (data->flags & QmlSimpleDeclarativeData::Extended)) {
+ data->context = 0;
+ } else {
+ p->declarativeData = 0;
+ }
+ }
+ d->contextObjects.clear();
+}
+
+void QmlContextPrivate::invalidateEngines()
+{
+ if (!engine)
+ return;
+ engine = 0;
+ for (QSet<QmlContext *>::ConstIterator iter = childContexts.begin();
+ iter != childContexts.end();
+ ++iter) {
+ (*iter)->d_func()->invalidateEngines();
+ }
+}
+
+/*!
+ Return the context's QmlEngine, or 0 if the context has no QmlEngine or the
+ QmlEngine was destroyed.
+*/
+QmlEngine *QmlContext::engine() const
+{
+ Q_D(const QmlContext);
+ return d->engine;
+}
+
+/*!
+ Return the context's parent QmlContext, or 0 if this context has no
+ parent or if the parent has been destroyed.
+*/
+QmlContext *QmlContext::parentContext() const
+{
+ Q_D(const QmlContext);
+ return d->parent;
+}
+
+/*!
+ Add a default \a object to this context. The object will be added after
+ any existing default objects.
+*/
+void QmlContext::addDefaultObject(QObject *object)
+{
+ Q_D(QmlContext);
+ d->addDefaultObject(object, QmlContextPrivate::NormalPriority);
+}
+
+/*!
+ Set a the \a value of the \a name property on this context.
+*/
+void QmlContext::setContextProperty(const QString &name, const QVariant &value)
+{
+ Q_D(QmlContext);
+ if (d->notifyIndex == -1)
+ d->notifyIndex = this->metaObject()->methodCount();
+
+ if (QmlMetaType::isObject(value.userType())) {
+ QObject *o = QmlMetaType::toQObject(value);
+ setContextProperty(name, o);
+ } else {
+ QHash<QString, int>::ConstIterator iter = d->propertyNames.find(name);
+ if(iter == d->propertyNames.end()) {
+ d->propertyNames.insert(name, d->propertyValues.count());
+ d->propertyValues.append(value);
+ } else {
+ d->propertyValues[*iter] = value;
+ QMetaObject::activate(this, *iter + d->notifyIndex, 0);
+ }
+ }
+}
+
+/*!
+ Set a the \a value of the \a name property on this context.
+
+ QmlContext does \b not take ownership of \a value.
+*/
+void QmlContext::setContextProperty(const QString &name, QObject *value)
+{
+ Q_D(QmlContext);
+ if (d->notifyIndex == -1)
+ d->notifyIndex = this->metaObject()->methodCount();
+
+ QObject::connect(value, SIGNAL(destroyed(QObject*)),
+ this, SLOT(objectDestroyed(QObject*)));
+
+ QHash<QString, int>::ConstIterator iter = d->propertyNames.find(name);
+ if(iter == d->propertyNames.end()) {
+ d->propertyNames.insert(name, d->propertyValues.count());
+ d->propertyValues.append(QVariant::fromValue(value));
+ } else {
+ int idx = *iter;
+ if (QmlMetaType::isObject(d->propertyValues.at(idx).userType())) {
+ QObject *old = QmlMetaType::toQObject(d->propertyValues.at(idx));
+ QObject::disconnect(old, SIGNAL(destroyed(QObject*)),
+ this, SLOT(objectDestroyed(QObject*)));
+ }
+ d->propertyValues[*iter] = QVariant::fromValue(value);
+ QMetaObject::activate(this, *iter + d->notifyIndex, 0);
+ }
+}
+
+/*!
+ Activate this bind context.
+
+ \sa QmlEngine::activeContext() QmlContext::activeContext()
+*/
+void QmlContext::activate()
+{
+ QmlEnginePrivate *ep = engine()->d_func();
+ ep->activeContexts.push(this);
+ ep->setCurrentBindContext(this);
+ ep->contextActivated(this);
+}
+
+/*!
+ Deactivate this bind context. The previously active bind context will
+ become active, or, if there was no previously active bind context, no
+ context will be active.
+
+ \sa QmlEngine::activeContext() QmlContext::activeContext()
+*/
+void QmlContext::deactivate()
+{
+ QmlEnginePrivate *ep = engine()->d_func();
+ Q_ASSERT(ep->activeContexts.top() == this);
+ ep->activeContexts.pop();
+ if (ep->activeContexts.isEmpty())
+ ep->setCurrentBindContext(0);
+ else
+ ep->setCurrentBindContext(ep->activeContexts.top());
+ ep->contextDeactivated(this);
+}
+
+/*!
+ Returns the currently active context, or 0 if no context is active.
+
+ This method is thread-safe. The active context is maintained individually
+ for each thread. This method is equivalent to
+ \code
+ QmlEngine::activeEngine()->activeContext()
+ \endcode
+*/
+QmlContext *QmlContext::activeContext()
+{
+ QmlEngine *engine = QmlEngine::activeEngine();
+ if (engine)
+ return engine->activeContext();
+ else
+ return 0;
+}
+
+/*!
+ Resolves the URL \a src relative to the URL of the
+ containing component. If \a src is absolute, it is
+ simply returned. If there is no containing component,
+ an empty URL is returned.
+
+ \sa QmlEngine::componentUrl(), setBaseUrl()
+*/
+QUrl QmlContext::resolvedUrl(const QUrl &src)
+{
+ QmlContext *ctxt = this;
+ if (src.isRelative()) {
+ if (ctxt) {
+ while(ctxt) {
+ if(ctxt->d_func()->url.isValid())
+ break;
+ else
+ ctxt = ctxt->parentContext();
+ }
+
+ if (ctxt)
+ return ctxt->d_func()->url.resolved(src);
+ }
+ return QUrl();
+ } else {
+ return src;
+ }
+}
+
+/*!
+ Resolves the component URI \a src relative to the URL of the
+ containing component, and according to the
+ \l {QmlEngine::nameSpacePaths()} {namespace paths} of the
+ context's engine, returning the resolved URL.
+
+ \sa QmlEngine::componentUrl(), setBaseUrl()
+*/
+QUrl QmlContext::resolvedUri(const QUrl &src)
+{
+ QmlContext *ctxt = this;
+ if (src.isRelative()) {
+ if (ctxt) {
+ while(ctxt) {
+ if (ctxt->d_func()->url.isValid())
+ break;
+ else
+ ctxt = ctxt->parentContext();
+ }
+
+ if (ctxt)
+ return ctxt->d_func()->engine->componentUrl(src, ctxt->d_func()->url);
+ }
+ return QUrl();
+ } else {
+ return ctxt->d_func()->engine->componentUrl(src, QUrl());
+ }
+}
+
+/*!
+ Explicitly sets the url both resolveUri() and resolveUrl() will
+ use for relative references to \a baseUrl.
+
+ Calling this function will override the url of the containing
+ component used by default.
+
+ \sa resolvedUrl(), resolvedUri()
+*/
+void QmlContext::setBaseUrl(const QUrl &baseUrl)
+{
+ d_func()->url = baseUrl;
+}
+
+void QmlContext::objectDestroyed(QObject *object)
+{
+ Q_D(QmlContext);
+ d->destroyed(object);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h
new file mode 100644
index 0000000..935c7ca
--- /dev/null
+++ b/src/declarative/qml/qmlcontext.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCONTEXT_H
+#define QMLCONTEXT_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qobject.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QmlEngine;
+class QmlRefCount;
+class QmlContextPrivate;
+class Q_DECLARATIVE_EXPORT QmlContext : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlContext)
+
+public:
+ QmlContext(QmlContext *parent, QObject *objParent=0);
+ virtual ~QmlContext();
+
+ QmlEngine *engine() const;
+ QmlContext *parentContext() const;
+
+ void addDefaultObject(QObject *);
+ void setContextProperty(const QString &, QObject *);
+ void setContextProperty(const QString &, const QVariant &);
+
+ void activate();
+ void deactivate();
+
+ static QmlContext *activeContext();
+
+ QUrl resolvedUri(const QUrl &);
+ QUrl resolvedUrl(const QUrl &);
+
+ void setBaseUrl(const QUrl &);
+
+private Q_SLOTS:
+ void objectDestroyed(QObject *);
+
+private:
+ friend class QmlEngine;
+ friend class QmlEnginePrivate;
+ friend class QmlExpression;
+ friend class QmlBasicScript;
+ friend class QmlContextScriptClass;
+ friend class QmlObjectScriptClass;
+ friend class QmlComponent;
+ friend class QmlScriptPrivate;
+ friend class QmlBoundSignalProxy;
+ friend class QmlSimpleDeclarativeData;
+ QmlContext(QmlEngine *);
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLCONTEXT_H
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
new file mode 100644
index 0000000..6f1e486
--- /dev/null
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCONTEXT_P_H
+#define QMLCONTEXT_P_H
+
+#include <qmlcontext.h>
+#include <private/qobject_p.h>
+#include <private/qmldeclarativedata_p.h>
+#include <qhash.h>
+#include <qscriptvalue.h>
+#include <QtCore/qset.h>
+
+QT_BEGIN_NAMESPACE
+class QmlContext;
+class QmlExpression;
+class QmlEngine;
+class QmlExpression;
+class QmlCompiledComponent;
+
+class QmlContextPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlContext)
+public:
+ QmlContextPrivate();
+
+ QmlContext *parent;
+ QmlEngine *engine;
+
+ QHash<QString, int> propertyNames;
+ QList<QVariant> propertyValues;
+ int notifyIndex;
+
+ QObjectList defaultObjects;
+ int highPriorityCount;
+
+ QScriptValueList scopeChain;
+
+ QUrl url;
+ QByteArray typeName;
+ int startLine;
+ int endLine;
+
+ void init();
+
+ void dump();
+ void dump(int depth);
+
+ void destroyed(QObject *);
+
+ enum Priority {
+ HighPriority,
+ NormalPriority
+ };
+ void addDefaultObject(QObject *, Priority);
+
+ void invalidateEngines();
+ QSet<QmlContext *> childContexts;
+ QSet<QmlExpression *> childExpressions;
+
+ QmlSimpleDeclarativeData contextData;
+ QObjectList contextObjects;
+};
+QT_END_NAMESPACE
+
+#endif // QMLCONTEXT_P_H
diff --git a/src/declarative/qml/qmlcustomparser.cpp b/src/declarative/qml/qmlcustomparser.cpp
new file mode 100644
index 0000000..e864df9
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcustomparser_p.h"
+#include "qmlcustomparser_p_p.h"
+#include "qmlparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlParser;
+
+/*!
+ \class QmlCustomParser
+ \brief The QmlCustomParser class allows you to add new arbitrary types to QML.
+ \internal
+
+ By subclassing QmlCustomParser, you can add an XML parser for
+ building a particular type.
+
+ The subclass must implement compile() and create(), and define
+ itself in the meta type system with one of the macros:
+
+ \code
+ QML_DEFINE_CUSTOM_PARSER(Name, parserClass)
+ \endcode
+
+ \code
+ QML_DEFINE_CUSTOM_PARSER_NS("XmlNamespaceUri", Name, parserClass)
+ \endcode
+*/
+
+/*
+ \fn QByteArray QmlCustomParser::compile(QXmlStreamReader& reader, bool *ok)
+
+ Upon entry to this function, \a reader is positioned on a
+ QXmlStreamReader::StartElement with the name specified when the
+ class was defined with the QML_DEFINE_CUSTOM_PARSER macro.
+
+ The custom parser must consume tokens from \a reader until the
+ EndElement matching the initial start element is reached, or until
+ error.
+
+ On return, \c *ok indicates success.
+
+ The returned QByteArray contains data meaningful only to the
+ custom parser; the type engine will pass this same data to
+ create() when making an instance of the data.
+
+ The QByteArray may be cached between executions of the system, so
+ it must contain correctly-serialized data (not, for example,
+ pointers to stack objects).
+*/
+
+/*
+ \fn QVariant QmlCustomParser::create(const QByteArray &data)
+
+ This function returns a QVariant containing the value represented
+ by \a data, which is a block of data previously returned by a call
+ to compile().
+
+ If the compile is for a type, the variant should be a pointer to
+ the correctly-named QObject subclass (i.e. the one defined by
+ QML_DEFINE_TYPE for the same-named type as this custom parser is
+ defined for).
+*/
+
+QmlCustomParserNode
+QmlCustomParserNodePrivate::fromObject(QmlParser::Object *root)
+{
+ QmlCustomParserNode rootNode;
+ rootNode.d->name = root->typeName;
+
+ for(QHash<QByteArray, Property *>::Iterator iter = root->properties.begin();
+ iter != root->properties.end();
+ ++iter) {
+
+ Property *p = *iter;
+
+ rootNode.d->properties << fromProperty(p);
+ }
+
+ return rootNode;
+}
+
+QmlCustomParserProperty
+QmlCustomParserNodePrivate::fromProperty(QmlParser::Property *p)
+{
+ QmlCustomParserProperty prop;
+ prop.d->name = p->name;
+ prop.d->isList = (p->values.count() > 1);
+
+ for(int ii = 0; ii < p->values.count(); ++ii) {
+ Value *v = p->values.at(ii);
+
+ // We skip fetched properties for now
+ if(v->object && v->object->type == -1)
+ continue;
+
+ if(v->object) {
+ QmlCustomParserNode node = fromObject(v->object);
+ prop.d->values << QVariant::fromValue(node);
+ } else {
+ prop.d->values << QVariant::fromValue(v->primitive());
+ }
+
+ }
+
+ return prop;
+}
+
+QmlCustomParserNode::QmlCustomParserNode()
+: d(new QmlCustomParserNodePrivate)
+{
+}
+
+QmlCustomParserNode::QmlCustomParserNode(const QmlCustomParserNode &other)
+: d(new QmlCustomParserNodePrivate)
+{
+ *this = other;
+}
+
+QmlCustomParserNode &QmlCustomParserNode::operator=(const QmlCustomParserNode &other)
+{
+ d->name = other.d->name;
+ d->properties = other.d->properties;
+ return *this;
+}
+
+QmlCustomParserNode::~QmlCustomParserNode()
+{
+ delete d; d = 0;
+}
+
+QByteArray QmlCustomParserNode::name() const
+{
+ return d->name;
+}
+
+QList<QmlCustomParserProperty> QmlCustomParserNode::properties() const
+{
+ return d->properties;
+}
+
+QmlCustomParserProperty::QmlCustomParserProperty()
+: d(new QmlCustomParserPropertyPrivate)
+{
+}
+
+QmlCustomParserProperty::QmlCustomParserProperty(const QmlCustomParserProperty &other)
+: d(new QmlCustomParserPropertyPrivate)
+{
+ *this = other;
+}
+
+QmlCustomParserProperty &QmlCustomParserProperty::operator=(const QmlCustomParserProperty &other)
+{
+ d->name = other.d->name;
+ d->isList = other.d->isList;
+ d->values = other.d->values;
+ return *this;
+}
+
+QmlCustomParserProperty::~QmlCustomParserProperty()
+{
+ delete d; d = 0;
+}
+
+QByteArray QmlCustomParserProperty::name() const
+{
+ return d->name;
+}
+
+bool QmlCustomParserProperty::isList() const
+{
+ return d->isList;
+}
+
+QList<QVariant> QmlCustomParserProperty::assignedValues() const
+{
+ return d->values;
+}
+
+QByteArray QmlCustomParser::compile(const QList<QmlCustomParserProperty> &, bool *ok)
+{
+ return QByteArray();
+}
+
+void QmlCustomParser::setCustomData(QObject *, const QByteArray &)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcustomparser_p.h b/src/declarative/qml/qmlcustomparser_p.h
new file mode 100644
index 0000000..e4e6089
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCUSTOMPARSER_H
+#define QMLCUSTOMPARSER_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qxmlstream.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qmlmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlCustomParserPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlCustomParserProperty
+{
+public:
+ QmlCustomParserProperty();
+ QmlCustomParserProperty(const QmlCustomParserProperty &);
+ QmlCustomParserProperty &operator=(const QmlCustomParserProperty &);
+ ~QmlCustomParserProperty();
+
+ QByteArray name() const;
+
+ bool isList() const;
+ QList<QVariant> assignedValues() const;
+
+private:
+ friend class QmlCustomParserNodePrivate;
+ friend class QmlCustomParserPropertyPrivate;
+ QmlCustomParserPropertyPrivate *d;
+};
+Q_DECLARE_METATYPE(QmlCustomParserProperty);
+
+class QmlCustomParserNodePrivate;
+class Q_DECLARATIVE_EXPORT QmlCustomParserNode
+{
+public:
+ QmlCustomParserNode();
+ QmlCustomParserNode(const QmlCustomParserNode &);
+ QmlCustomParserNode &operator=(const QmlCustomParserNode &);
+ ~QmlCustomParserNode();
+
+ QByteArray name() const;
+
+ QList<QmlCustomParserProperty> properties() const;
+
+private:
+ friend class QmlCustomParserNodePrivate;
+ QmlCustomParserNodePrivate *d;
+};
+Q_DECLARE_METATYPE(QmlCustomParserNode);
+
+class Q_DECLARATIVE_EXPORT QmlCustomParser
+{
+public:
+ virtual ~QmlCustomParser() {}
+
+ virtual QByteArray compile(const QList<QmlCustomParserProperty> &, bool *ok);
+ virtual void setCustomData(QObject *, const QByteArray &);
+};
+#define QML_DEFINE_CUSTOM_TYPE(TYPE, NAME, CUSTOMTYPE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterCustomType<TYPE>(#NAME, #TYPE, new CUSTOMTYPE));
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/qml/qmlcustomparser_p_p.h b/src/declarative/qml/qmlcustomparser_p_p.h
new file mode 100644
index 0000000..96e9b32
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser_p_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCUSTOMPARSER_P_H
+#define QMLCUSTOMPARSER_P_H
+
+#include <QtCore/qglobal.h>
+#include "qmlcustomparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QmlParser
+{
+ class Object;
+ class Property;
+};
+
+class QmlCustomParserNodePrivate
+{
+public:
+ QByteArray name;
+ QList<QmlCustomParserProperty> properties;
+
+ static QmlCustomParserNode fromObject(QmlParser::Object *);
+ static QmlCustomParserProperty fromProperty(QmlParser::Property *);
+};
+
+class QmlCustomParserPropertyPrivate
+{
+public:
+ QmlCustomParserPropertyPrivate()
+ : isList(false) {}
+
+ QByteArray name;
+ bool isList;
+ QList<QVariant> values;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCUSTOMPARSER_P_H
diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h
new file mode 100644
index 0000000..fb7a015
--- /dev/null
+++ b/src/declarative/qml/qmldeclarativedata_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDECLARATIVEDATA_P_H
+#define QMLDECLARATIVEDATA_P_H
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlSimpleDeclarativeData : public QDeclarativeData
+{
+public:
+ QmlSimpleDeclarativeData() : flags(0), context(0) {}
+
+ virtual void destroyed(QObject *);
+ enum Flag { Extended = 0x00000001 };
+ quint32 flags;
+ QmlContext *context;
+};
+
+class QmlExtendedDeclarativeData : public QmlSimpleDeclarativeData
+{
+public:
+ QmlExtendedDeclarativeData() { flags = Extended; }
+
+ virtual void destroyed(QObject *);
+ QHash<int, QObject *> attachedProperties;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLDECLARATIVEDATA_P_H
diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp
new file mode 100644
index 0000000..673520e
--- /dev/null
+++ b/src/declarative/qml/qmldom.cpp
@@ -0,0 +1,1519 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldom.h"
+#include "qmldom_p.h"
+#include "private/qmlcompiler_p.h"
+#include "private/qmlengine_p.h"
+#include "qmlcompiledcomponent_p.h"
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstring.h>
+
+#include "qmlscriptparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlDomDocumentPrivate::QmlDomDocumentPrivate()
+: root(0)
+{
+}
+
+QmlDomDocumentPrivate::QmlDomDocumentPrivate(const QmlDomDocumentPrivate &other)
+: QSharedData(other), root(0)
+{
+ root = other.root;
+ if (root) root->addref();
+}
+
+QmlDomDocumentPrivate::~QmlDomDocumentPrivate()
+{
+ if (root) root->release();
+}
+
+/*!
+ \class QmlDomDocument
+ \internal
+ \brief The QmlDomDocument class represents the root of a QML document
+
+ A QML document is a self-contained snippet of QML, usually contained in a
+ single file. Each document has a version number, accessible through
+ QmlDomDocument::version(), and a root object, accessible through
+ QmlDomDocument::rootObject().
+
+ The QmlDomDocument class allows the programmer to load a QML document, by
+ calling QmlDomDocument::load(), manipulate it and save it to textual form
+ by calling QmlDomDocument::save(). By using the QML DOM API, editors can
+ non-destructively modify a QML document even if they only understand a
+ subset of the total QML functionality.
+
+ The following example loads a QML file from disk, and prints out its root
+ object type and the properties assigned in the root object.
+ \code
+ QFile file(inputFileName);
+ file.open(QIODevice::ReadOnly);
+ QByteArray xmlData = file.readAll();
+
+ QDomDocument document;
+ document.load(xmlData);
+
+ QDomObject rootObject = document.rootObject();
+ qDebug() << rootObject.objectType();
+ foreach(QmlDomProperty property, rootObject.properties())
+ qDebug() << property.propertyName();
+ \endcode
+*/
+
+/*!
+ Construct an empty QmlDomDocument.
+*/
+QmlDomDocument::QmlDomDocument()
+: d(new QmlDomDocumentPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomDocument.
+*/
+QmlDomDocument::QmlDomDocument(const QmlDomDocument &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomDocument
+*/
+QmlDomDocument::~QmlDomDocument()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomDocument.
+*/
+QmlDomDocument &QmlDomDocument::operator=(const QmlDomDocument &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the version number of the Qml document. Currently only version
+ 1 exists.
+*/
+int QmlDomDocument::version() const
+{
+ return 1;
+}
+
+/*!
+ Return the URIs listed by "import <dir>" in the qml.
+*/
+QList<QUrl> QmlDomDocument::imports() const
+{
+ return d->imports;
+}
+
+/*!
+ Loads a QmlDomDocument from \a data. \a data should be valid QML
+ data. On success, true is returned. If the \a data is malformed, false
+ is returned and QmlDomDocument::loadError() contains an error description.
+
+ \sa QmlDomDocument::save() QmlDomDocument::loadError()
+*/
+bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data, const QUrl &url)
+{
+ Q_UNUSED(engine);
+ d->errors.clear();
+ d->imports.clear();
+
+ QmlCompiledComponent component;
+ QmlCompiler compiler;
+
+ QmlCompositeTypeData *td = ((QmlEnginePrivate *)QmlEnginePrivate::get(engine))->typeManager.getImmediate(data, url);
+
+ if(td->status == QmlCompositeTypeData::Error) {
+ d->errors = td->errors;
+ td->release();
+ return false;
+ } else if(td->status == QmlCompositeTypeData::Waiting) {
+ QmlError error;
+ error.setDescription(QLatin1String("QmlDomDocument supports local types only"));
+ d->errors << error;
+ td->release();
+ return false;
+ }
+
+ compiler.compile(engine, td, &component);
+
+ if (compiler.isError()) {
+ d->errors = compiler.errors();
+ td->release();
+ return false;
+ }
+
+ for (int i = 0; i < td->data.imports().size(); ++i) {
+ d->imports += QUrl(td->data.imports().at(i).uri);
+ }
+
+ if (td->data.tree()) {
+ td->data.tree()->dump();
+ d->root = td->data.tree();
+ d->root->addref();
+ }
+
+ return true;
+}
+
+
+/*!
+ Returns the last load errors. The load errors will be reset after a
+ successful call to load().
+
+ \sa load()
+*/
+QList<QmlError> QmlDomDocument::errors() const
+{
+ return d->errors;
+}
+
+/*!
+ Return a saved copy of the QmlDomDocument. The returned data will be valid
+ QML XML data.
+
+ \sa load()
+*/
+QByteArray QmlDomDocument::save() const
+{
+ return QByteArray();
+}
+
+/*!
+ Returns the document's root object, or an invalid QmlDomObject if the
+ document has no root.
+
+ In the sample QML below, the root object will be the QFxItem type.
+ \qml
+Item {
+ Text {
+ text: "Hello World"
+ }
+}
+ \endqml
+*/
+QmlDomObject QmlDomDocument::rootObject() const
+{
+ QmlDomObject rv;
+ rv.d->object = d->root;
+ if (rv.d->object) rv.d->object->addref();
+ return rv;
+}
+
+QmlDomPropertyPrivate::QmlDomPropertyPrivate()
+: property(0)
+{
+}
+
+QmlDomPropertyPrivate::QmlDomPropertyPrivate(const QmlDomPropertyPrivate &other)
+: QSharedData(other), property(0)
+{
+ property = other.property;
+ if (property) property->addref();
+}
+
+QmlDomPropertyPrivate::~QmlDomPropertyPrivate()
+{
+ if (property) property->release();
+}
+
+/*!
+ \class QmlDomProperty
+ \internal
+ \brief The QmlDomProperty class represents one property assignment in the
+ QML DOM tree
+
+ Properties in QML can be assigned QML \l {QmlDomValue}{values}.
+
+ \sa QmlDomObject
+*/
+
+/*!
+ Construct an invalid QmlDomProperty.
+*/
+QmlDomProperty::QmlDomProperty()
+: d(new QmlDomPropertyPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomProperty.
+*/
+QmlDomProperty::QmlDomProperty(const QmlDomProperty &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomProperty.
+*/
+QmlDomProperty::~QmlDomProperty()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomProperty.
+*/
+QmlDomProperty &QmlDomProperty::operator=(const QmlDomProperty &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the name of this property.
+
+ \qml
+Text {
+ x: 10
+ y: 10
+ font.bold: true
+}
+ \endqml
+
+ As illustrated above, a property name can be a simple string, such as "x" or
+ "y", or a more complex "dot property", such as "font.bold". In both cases
+ the full name is returned ("x", "y" and "font.bold") by this method.
+
+ For dot properties, a split version of the name can be accessed by calling
+ QmlDomProperty::propertyNameParts().
+
+ \sa QmlDomProperty::propertyNameParts()
+*/
+QByteArray QmlDomProperty::propertyName() const
+{
+ return d->propertyName;
+}
+
+/*!
+ Return the name of this property, split into multiple parts in the case
+ of dot properties.
+
+ \qml
+Text {
+ x: 10
+ y: 10
+ font.bold: true
+}
+ \endqml
+
+ For each of the properties shown above, this method would return ("x"),
+ ("y") and ("font", "bold").
+
+ \sa QmlDomProperty::propertyName()
+*/
+QList<QByteArray> QmlDomProperty::propertyNameParts() const
+{
+ if (d->propertyName.isEmpty()) return QList<QByteArray>();
+ else return d->propertyName.split('.');
+}
+
+/*!
+ Return true if this property is used as a default property in the QML
+ document.
+
+ \qml
+<Text text="hello"/>
+<Text>hello</Text>
+ \endqml
+
+ The above two examples return the same DOM tree, except that the second has
+ the default property flag set on the text property. Observe that whether
+ or not a property has isDefaultProperty set is determined by how the
+ property is used, and not only by whether the property is the types default
+ property.
+*/
+bool QmlDomProperty::isDefaultProperty() const
+{
+ return d->property && d->property->isDefault;
+}
+
+/*!
+ Returns the QmlDomValue that is assigned to this property, or an invalid
+ QmlDomValue if no value is assigned.
+*/
+QmlDomValue QmlDomProperty::value() const
+{
+ QmlDomValue rv;
+ if (d->property) {
+ rv.d->property = d->property;
+ rv.d->value = d->property->values.at(0);
+ rv.d->property->addref();
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Sets the QmlDomValue that is assigned to this property to \a value.
+*/
+void QmlDomProperty::setValue(const QmlDomValue &value)
+{
+ Q_UNUSED(value);
+ qWarning("QmlDomProperty::setValue(const QmlDomValue &): Not Implemented");
+}
+
+/*!
+ Returns the position in the input data where the property ID startd, or 0 if
+ the property is invalid.
+*/
+int QmlDomProperty::position() const
+{
+ if (d && d->property) {
+ return d->property->location.range.offset;
+ } else
+ return 0;
+}
+
+/*!
+ Returns the length in the input data from where the property ID started upto
+ the end of it, or 0 if the property is invalid.
+*/
+int QmlDomProperty::length() const
+{
+ if (d && d->property)
+ return d->property->location.range.length;
+ else
+ return 0;
+}
+
+QmlDomObjectPrivate::QmlDomObjectPrivate()
+: object(0), isVirtualComponent(false)
+{
+}
+
+QmlDomObjectPrivate::QmlDomObjectPrivate(const QmlDomObjectPrivate &other)
+: QSharedData(other), object(0), isVirtualComponent(false)
+{
+ object = other.object;
+ if (object) object->addref();
+ isVirtualComponent = other.isVirtualComponent;
+}
+
+QmlDomObjectPrivate::~QmlDomObjectPrivate()
+{
+ if (object) object->release();
+}
+
+QmlDomObjectPrivate::Properties
+QmlDomObjectPrivate::properties() const
+{
+ Properties rv;
+
+ for (QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
+ object->properties.begin();
+ iter != object->properties.end();
+ ++iter) {
+
+ rv << properties(*iter);
+
+ }
+ return rv;
+}
+
+QmlDomObjectPrivate::Properties
+QmlDomObjectPrivate::properties(QmlParser::Property *property) const
+{
+ Properties rv;
+
+ if (property->value) {
+
+ for (QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
+ property->value->properties.begin();
+ iter != property->value->properties.end();
+ ++iter) {
+
+ rv << properties(*iter);
+
+ }
+
+ QByteArray name(property->name + ".");
+ for (Properties::Iterator iter = rv.begin(); iter != rv.end(); ++iter)
+ iter->second.prepend(name);
+
+ } else {
+
+ // We don't display "id" sets as a property in the dom
+ if (property->values.count() != 1 ||
+ property->values.at(0)->type != QmlParser::Value::Id)
+ rv << qMakePair(property, property->name);
+
+ }
+
+ return rv;
+}
+
+/*!
+ \class QmlDomObject
+ \internal
+ \brief The QmlDomObject class represents an object instantiation.
+
+ Each object instantiated in a QML file has a corresponding QmlDomObject
+ node in the QML DOM.
+
+ In addition to the type information that determines the object to
+ instantiate, QmlDomObject's also have a set of associated QmlDomProperty's.
+ Each QmlDomProperty represents a QML property assignment on the instantiated
+ object. For example,
+
+ \qml
+QGraphicsWidget {
+ opacity: 0.5
+ size: "100x100"
+}
+ \endqml
+
+ describes a single QmlDomObject - "QGraphicsWidget" - with two properties,
+ "opacity" and "size". Obviously QGraphicsWidget has many more properties than just
+ these two, but the QML DOM representation only contains those assigned
+ values (or bindings) in the QML file.
+
+ The DOM tree can be modified to include new property assignments by calling
+ QmlDomObject::addProperty(). Existing property assignments can be modified
+ through the QmlDomProperty::setValue() method, or removed entirely by
+ calling QmlDomObject::removeProperty().
+*/
+
+/*!
+ Construct an invalid QmlDomObject.
+*/
+QmlDomObject::QmlDomObject()
+: d(new QmlDomObjectPrivate)
+{
+}
+
+/*!
+ Construct a new QmlDomObject with the specified \a objectType.
+*/
+QmlDomObject::QmlDomObject(const QByteArray &objectType)
+: d(new QmlDomObjectPrivate)
+{
+ Q_UNUSED(objectType);
+ qWarning("QmlDomObject::QmlDomObject(const QByteArray &): Not implemented");
+}
+
+/*!
+ Create a copy of \a other QmlDomObject.
+*/
+QmlDomObject::QmlDomObject(const QmlDomObject &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomObject.
+*/
+QmlDomObject::~QmlDomObject()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomObject.
+*/
+QmlDomObject &QmlDomObject::operator=(const QmlDomObject &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns true if this is a valid QmlDomObject, false otherwise.
+*/
+bool QmlDomObject::isValid() const
+{
+ return d->object != 0;
+}
+
+/*!
+ Returns the type name of this object.
+
+ For example, the type of this object would be "QGraphicsWidget".
+ \qml
+QGraphicsWidget { }
+ \endqml
+*/
+QByteArray QmlDomObject::objectType() const
+{
+ if (d->object) return d->object->typeName;
+ else return QByteArray();
+}
+
+/*!
+ Returns the QML id assigned to this object, or an empty QByteArray if no id
+ has been assigned.
+
+ For example, the object id of this object would be "MyText".
+ \qml
+Text { id: MyText }
+ \endqml
+*/
+QByteArray QmlDomObject::objectId() const
+{
+ if (d->object) return d->object->id;
+ else return QByteArray();
+}
+
+/*!
+ Set the object \a id. If any other object within the DOM tree has the same
+ id, the other object's id will be cleared.
+*/
+void QmlDomObject::setObjectId(const QByteArray &id)
+{
+ Q_UNUSED(id);
+ qWarning("QmlDomObject::setObjectId(const QByteArray &): Not implemented");
+}
+
+
+/*!
+ Returns the list of assigned properties on this object.
+
+ In the following example, "text" and "x" properties would be returned.
+ \qml
+Text {
+ text: "Hello world!"
+ x: 100
+}
+ \endqml
+*/
+QList<QmlDomProperty> QmlDomObject::properties() const
+{
+ QList<QmlDomProperty> rv;
+
+ if (!d->object)
+ return rv;
+
+ QmlDomObjectPrivate::Properties properties = d->properties();
+ for (int ii = 0; ii < properties.count(); ++ii) {
+
+ QmlDomProperty domProperty;
+ domProperty.d->property = properties.at(ii).first;
+ domProperty.d->property->addref();
+ domProperty.d->propertyName = properties.at(ii).second;
+ rv << domProperty;
+
+ }
+
+ if (d->object->defaultProperty) {
+ QmlDomProperty domProperty;
+ domProperty.d->property = d->object->defaultProperty;
+ domProperty.d->property->addref();
+ domProperty.d->propertyName = d->object->defaultProperty->name;
+ rv << domProperty;
+ }
+
+ return rv;
+}
+
+/*!
+ Returns the object's \a name property if a value has been assigned to
+ it, or an invalid QmlDomProperty otherwise.
+
+ In the example below, \c {object.property("source")} would return a valid
+ QmlDomProperty, and \c {object.property("tile")} an invalid QmlDomProperty.
+
+ \qml
+Image { source: "sample.jpg" }
+ \endqml
+*/
+QmlDomProperty QmlDomObject::property(const QByteArray &name) const
+{
+ QList<QmlDomProperty> props = properties();
+ for (int ii = 0; ii < props.count(); ++ii)
+ if (props.at(ii).propertyName() == name)
+ return props.at(ii);
+ return QmlDomProperty();
+}
+
+/*!
+ Remove the property \a name from this object, if it exists. Otherwise does
+ nothing.
+*/
+void QmlDomObject::removeProperty(const QByteArray &name)
+{
+ Q_UNUSED(name);
+ qWarning("QmlDomObject::removeProperty(const QByteArray &): Not implemented");
+}
+
+/*!
+ Adds the property \a name with the specified \a value to this object. If
+ a property by \a name already exists, it will be removed.
+*/
+void QmlDomObject::addProperty(const QByteArray &name, const QmlDomValue &value)
+{
+ Q_UNUSED(name);
+ Q_UNUSED(value);
+ qWarning("QmlDomObject::addProperty(const QByteArray &, const QmlDomValue &): Not implemented");
+}
+
+/*!
+ Returns true if this object is a custom type. Custom types are special
+ types that allow embeddeding non-QML data, such as SVG or HTML data,
+ directly into QML files.
+
+ \note Currently this method will always return false, and is a placekeeper
+ for future functionality.
+
+ \sa QmlDomObject::customTypeData()
+*/
+bool QmlDomObject::isCustomType() const
+{
+ return false;
+}
+
+/*!
+ Sets the custom type \a data. If this type is not a custom type, this
+ method does nothing.
+
+ \sa QmlDomObject::isCustomType() QmlDomObject::customTypeData()
+*/
+void QmlDomObject::setCustomTypeData(const QByteArray &data)
+{
+ Q_UNUSED(data);
+ qWarning("QmlDomObject::setCustomTypeData(const QByteArray &): Not implemented");
+}
+
+/*!
+ If this object represents a custom type, returns the data associated with
+ the custom type, otherwise returns an empty QByteArray().
+ QmlDomObject::isCustomType() can be used to check if this object represents
+ a custom type.
+*/
+QByteArray QmlDomObject::customTypeData() const
+{
+ return QByteArray();
+}
+
+/*!
+ Returns true if this object is a sub-component object. Sub-component
+ objects can be converted into QmlDomComponent instances by calling
+ QmlDomObject::toComponent().
+
+ \sa QmlDomObject::toComponent()
+*/
+bool QmlDomObject::isComponent() const
+{
+ return d->isVirtualComponent ||
+ (d->object && d->object->typeName == "Component");
+}
+
+/*!
+ Returns a QmlDomComponent for this object if it is a sub-component, or
+ an invalid QmlDomComponent if not. QmlDomObject::isComponent() can be used
+ to check if this object represents a sub-component.
+
+ \sa QmlDomObject::isComponent()
+*/
+QmlDomComponent QmlDomObject::toComponent() const
+{
+ QmlDomComponent rv;
+ if (isComponent())
+ rv.d = d;
+ return rv;
+}
+
+/*!
+ Returns the position in the input data where the property assignment started
+, or 0 if the property is invalid.
+*/
+int QmlDomObject::position() const
+{
+ if (d && d->object)
+ return d->object->location.range.offset;
+ else
+ return 0;
+}
+
+/*!
+ Returns the length in the input data from where the property assignment star
+ted upto the end of it, or 0 if the property is invalid.
+*/
+int QmlDomObject::length() const
+{
+ if (d && d->object)
+ return d->object->location.range.length;
+ else
+ return 0;
+}
+
+QmlDomBasicValuePrivate::QmlDomBasicValuePrivate()
+: value(0)
+{
+}
+
+QmlDomBasicValuePrivate::QmlDomBasicValuePrivate(const QmlDomBasicValuePrivate &other)
+: QSharedData(other), value(0)
+{
+ value = other.value;
+ if (value) value->addref();
+}
+
+QmlDomBasicValuePrivate::~QmlDomBasicValuePrivate()
+{
+ if (value) value->release();
+}
+
+/*!
+ \class QmlDomValueLiteral
+ \internal
+ \brief The QmlDomValueLiteral class represents a literal value.
+
+ A literal value is a simple value, written inline with the QML. In the
+ example below, the "x", "y" and "color" properties are being assigned
+ literal values.
+
+ \qml
+Rect {
+ x: 10
+ y: 10
+ color: "red"
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::QmlDomValueLiteral():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::QmlDomValueLiteral(const QmlDomValueLiteral &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::~QmlDomValueLiteral()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueLiteral.
+*/
+QmlDomValueLiteral &QmlDomValueLiteral::operator=(const QmlDomValueLiteral &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the literal value.
+
+ In the example below, the literal value will be the string "10".
+ \qml
+Rect { x: 10 }
+ \endqml
+*/
+QString QmlDomValueLiteral::literal() const
+{
+ if (d->value) return d->value->primitive();
+ else return QString();
+}
+
+/*!
+ Sets the literal \a value.
+*/
+void QmlDomValueLiteral::setLiteral(const QString &value)
+{
+ Q_UNUSED(value);
+ qWarning("QmlDomValueLiteral::setLiteral(const QString &): Not implemented");
+}
+
+/*!
+ \class QmlDomValueBinding
+ \internal
+ \brief The QmlDomValueBinding class represents a property binding.
+
+ A property binding is an ECMAScript expression assigned to a property. In
+ the example below, the "x" property is being assigned a property binding.
+
+ \qml
+Rect { x: Other.x }
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueBinding.
+*/
+QmlDomValueBinding::QmlDomValueBinding():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueBinding.
+*/
+QmlDomValueBinding::QmlDomValueBinding(const QmlDomValueBinding &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueBinding.
+*/
+QmlDomValueBinding::~QmlDomValueBinding()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueBinding.
+*/
+QmlDomValueBinding &QmlDomValueBinding::operator=(const QmlDomValueBinding &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the binding expression.
+
+ In the example below, the string "Other.x" will be returned.
+ \qml
+Rect { x: Other.x }
+ \endqml
+*/
+QString QmlDomValueBinding::binding() const
+{
+ if (d->value)
+ return d->value->value.asScript();
+ else
+ return QString();
+}
+
+/*!
+ Sets the binding \a expression.
+*/
+void QmlDomValueBinding::setBinding(const QString &expression)
+{
+ Q_UNUSED(expression);
+ qWarning("QmlDomValueBinding::setBinding(const QString &): Not implemented");
+}
+
+/*!
+ \class QmlDomValueValueSource
+ \internal
+ \brief The QmlDomValueValueSource class represents a value source assignment value.
+
+ In QML, value sources are special value generating types that may be
+ assigned to properties. Value sources inherit the QmlPropertyValueSource
+ class. In the example below, the "x" property is being assigned the
+ NumericAnimation value source.
+
+ \qml
+Rect {
+ x: NumericAnimation {
+ from: 0
+ to: 100
+ repeat: true
+ running: true
+ }
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::QmlDomValueValueSource():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::QmlDomValueValueSource(const QmlDomValueValueSource &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::~QmlDomValueValueSource()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueValueSource.
+*/
+QmlDomValueValueSource &QmlDomValueValueSource::operator=(const QmlDomValueValueSource &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the value source object.
+
+ In the example below, an object representing the NumericAnimation will be
+ returned.
+ \qml
+Rect {
+ x: NumericAnimation {
+ from: 0
+ to: 100
+ repeat: true
+ running: true
+ }
+}
+ \endqml
+*/
+QmlDomObject QmlDomValueValueSource::object() const
+{
+ QmlDomObject rv;
+ if (d->value) {
+ rv.d->object = d->value->object;
+ rv.d->object->addref();
+ }
+ return rv;
+}
+
+/*!
+ Sets the value source \a object.
+*/
+void QmlDomValueValueSource::setObject(const QmlDomObject &object)
+{
+ Q_UNUSED(object);
+ qWarning("QmlDomValueValueSource::setObject(const QmlDomObject &): Not implemented");
+}
+
+QmlDomValuePrivate::QmlDomValuePrivate()
+: property(0), value(0)
+{
+}
+
+QmlDomValuePrivate::QmlDomValuePrivate(const QmlDomValuePrivate &other)
+: QSharedData(other), property(0), value(0)
+{
+ property = other.property;
+ value = other.value;
+ if (property) property->addref();
+ if (value) value->addref();
+}
+
+QmlDomValuePrivate::~QmlDomValuePrivate()
+{
+ if (property) property->release();
+ if (value) value->release();
+}
+
+/*!
+ \class QmlDomValue
+ \internal
+ \brief The QmlDomValue class represents a generic Qml value.
+
+ QmlDomValue's can be assigned to QML \l {QmlDomProperty}{properties}. In
+ QML, properties can be assigned various different values, including basic
+ literals, property bindings, property value sources, objects and lists of
+ values. The QmlDomValue class allows a programmer to determine the specific
+ value type being assigned and access more detailed information through a
+ corresponding value type class.
+
+ For example, in the following example,
+
+ \qml
+Text {
+ text: "Hello World!"
+ y: Other.y
+}
+ \endqml
+
+ The text property is being assigned a literal, and the y property a property
+ binding. To output the values assigned to the text and y properties in the
+ above example from C++,
+
+ \code
+ QmlDomDocument document;
+ QmlDomObject root = document.rootObject();
+
+ QmlDomProperty text = root.property("text");
+ if (text.value().isLiteral()) {
+ QmlDomValueLiteral literal = text.value().toLiteral();
+ qDebug() << literal.literal();
+ }
+
+ QmlDomProperty y = root.property("y");
+ if (y.value().isBinding()) {
+ QmlDomValueBinding binding = y.value().toBinding();
+ qDebug() << binding.binding();
+ }
+ \endcode
+*/
+
+/*!
+ Construct an invalid QmlDomValue.
+*/
+QmlDomValue::QmlDomValue()
+: d(new QmlDomValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValue.
+*/
+QmlDomValue::QmlDomValue(const QmlDomValue &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValue
+*/
+QmlDomValue::~QmlDomValue()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValue.
+*/
+QmlDomValue &QmlDomValue::operator=(const QmlDomValue &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \enum QmlDomValue::Type
+
+ The type of the QmlDomValue node.
+
+ \value Invalid The QmlDomValue is invalid.
+ \value Literal The QmlDomValue is a literal value assignment. Use QmlDomValue::toLiteral() to access the type instance.
+ \value PropertyBinding The QmlDomValue is a property binding. Use QmlDomValue::toBinding() to access the type instance.
+ \value ValueSource The QmlDomValue is a property value source. Use QmlDomValue::toValueSource() to access the type instance.
+ \value Object The QmlDomValue is an object assignment. Use QmlDomValue::toObject() to access the type instnace.
+ \value List The QmlDomValue is a list of other values. Use QmlDomValue::toList() to access the type instance.
+*/
+
+/*!
+ Returns the type of this QmlDomValue.
+*/
+QmlDomValue::Type QmlDomValue::type() const
+{
+ if (d->property)
+ if (QmlMetaType::isList(d->property->type) ||
+ QmlMetaType::isQmlList(d->property->type) ||
+ (d->property && d->property->values.count() > 1))
+ return List;
+
+ QmlParser::Value *value = d->value;
+ if (!value && !d->property)
+ return Invalid;
+
+ switch(value->type) {
+ case QmlParser::Value::Unknown:
+ return Invalid;
+ case QmlParser::Value::Literal:
+ return Literal;
+ case QmlParser::Value::PropertyBinding:
+ return PropertyBinding;
+ case QmlParser::Value::ValueSource:
+ return ValueSource;
+ case QmlParser::Value::Component:
+ case QmlParser::Value::CreatedObject:
+ return Object;
+ case QmlParser::Value::SignalObject:
+ return Invalid;
+ case QmlParser::Value::SignalExpression:
+ return Literal;
+ case QmlParser::Value::Id:
+ return Invalid;
+ }
+ return Invalid;
+}
+
+/*!
+ Returns true if this is an invalid value, otherwise false.
+*/
+bool QmlDomValue::isInvalid() const
+{
+ return type() == Invalid;
+}
+
+/*!
+ Returns true if this is a literal value, otherwise false.
+*/
+bool QmlDomValue::isLiteral() const
+{
+ return type() == Literal;
+}
+
+/*!
+ Returns true if this is a property binding value, otherwise false.
+*/
+bool QmlDomValue::isBinding() const
+{
+ return type() == PropertyBinding;
+}
+
+/*!
+ Returns true if this is a value source value, otherwise false.
+*/
+bool QmlDomValue::isValueSource() const
+{
+ return type() == ValueSource;
+}
+
+/*!
+ Returns true if this is an object value, otherwise false.
+*/
+bool QmlDomValue::isObject() const
+{
+ return type() == Object;
+}
+
+/*!
+ Returns true if this is a list value, otherwise false.
+*/
+bool QmlDomValue::isList() const
+{
+ return type() == List;
+}
+
+/*!
+ Returns a QmlDomValueLiteral if this value is a literal type, otherwise
+ returns an invalid QmlDomValueLiteral.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueLiteral QmlDomValue::toLiteral() const
+{
+ QmlDomValueLiteral rv;
+ if (type() == Literal) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomValueBinding if this value is a property binding type,
+ otherwise returns an invalid QmlDomValueBinding.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueBinding QmlDomValue::toBinding() const
+{
+ QmlDomValueBinding rv;
+ if (type() == PropertyBinding) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomValueValueSource if this value is a property value source
+ type, otherwise returns an invalid QmlDomValueValueSource.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueValueSource QmlDomValue::toValueSource() const
+{
+ QmlDomValueValueSource rv;
+ if (type() == ValueSource) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomObject if this value is an object assignment type, otherwise
+ returns an invalid QmlDomObject.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomObject QmlDomValue::toObject() const
+{
+ QmlDomObject rv;
+ if (type() == Object) {
+ rv.d->object = d->value->object;
+ rv.d->object->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomList if this value is a list type, otherwise returns an
+ invalid QmlDomList.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomList QmlDomValue::toList() const
+{
+ QmlDomList rv;
+ if (type() == List) {
+ rv.d = d;
+ }
+ return rv;
+}
+
+/*!
+ Returns the position in the input data where the property value startd, or 0
+ if the value is invalid.
+*/
+int QmlDomValue::position() const
+{
+ if (type() == Invalid)
+ return 0;
+ else
+ return d->value->location.range.offset;
+}
+
+/*!
+ Returns the length in the input data from where the property value started u
+pto the end of it, or 0 if the value is invalid.
+*/
+int QmlDomValue::length() const
+{
+ if (type() == Invalid)
+ return 0;
+ else
+ return d->value->location.range.length;
+}
+
+/*!
+ \class QmlDomList
+ \internal
+ \brief The QmlDomList class represents a list of values assigned to a QML property.
+
+ Lists of values can be assigned to properties. For example, the following
+ example assigns multiple objects to Item's "children" property
+ \qml
+Item {
+ children: [
+ Text { },
+ Rect { }
+ ]
+}
+ \endqml
+
+ Lists can also be implicitly created by assigning multiple
+ \l {QmlDomValueValueSource}{value sources} or constants to a property.
+ \qml
+Item {
+ x: 10
+ x: NumericAnimation {
+ running: false
+ from: 0
+ to: 100
+ }
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomList.
+*/
+QmlDomList::QmlDomList()
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomList.
+*/
+QmlDomList::QmlDomList(const QmlDomList &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomList.
+*/
+QmlDomList::~QmlDomList()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomList.
+*/
+QmlDomList &QmlDomList::operator=(const QmlDomList &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns the list of QmlDomValue's.
+*/
+QList<QmlDomValue> QmlDomList::values() const
+{
+ QList<QmlDomValue> rv;
+ if (!d->property)
+ return rv;
+
+ for (int ii = 0; ii < d->property->values.count(); ++ii) {
+ QmlDomValue v;
+ v.d->value = d->property->values.at(ii);
+ v.d->value->addref();
+ rv << v;
+ }
+
+ return rv;
+}
+
+/*!
+ Set the list of QmlDomValue's to \a values.
+*/
+void QmlDomList::setValues(const QList<QmlDomValue> &values)
+{
+ Q_UNUSED(values);
+ qWarning("QmlDomList::setValues(const QList<QmlDomValue> &): Not implemented");
+}
+
+
+/*!
+ \class QmlDomComponent
+ \internal
+ \brief The QmlDomComponent class represents sub-component within a QML document.
+
+ Sub-components are QmlComponents defined within a QML document. The
+ following example shows the definition of a sub-component with the id
+ "ListDelegate".
+
+ \qml
+Item {
+ Component {
+ id: ListDelegate
+ Text {
+ text: modelData.text
+ }
+ }
+}
+ \endqml
+
+ Like QmlDomDocument's, components contain a single root object.
+*/
+
+/*!
+ Construct an empty QmlDomComponent.
+*/
+QmlDomComponent::QmlDomComponent()
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomComponent.
+*/
+QmlDomComponent::QmlDomComponent(const QmlDomComponent &other)
+: QmlDomObject(other)
+{
+}
+
+/*!
+ Destroy the QmlDomComponent.
+*/
+QmlDomComponent::~QmlDomComponent()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomComponent.
+*/
+QmlDomComponent &QmlDomComponent::operator=(const QmlDomComponent &other)
+{
+ static_cast<QmlDomObject &>(*this) = other;
+ return *this;
+}
+
+/*!
+ Returns the component's root object.
+
+ In the example below, the root object is the "Text" object.
+ \qml
+Item {
+ Component {
+ id: ListDelegate
+ Text {
+ text: modelData.text
+ }
+ }
+}
+ \endqml
+*/
+QmlDomObject QmlDomComponent::componentRoot() const
+{
+ QmlDomObject rv;
+ if (d->isVirtualComponent) {
+ rv.d->object = d->object;
+ rv.d->object->addref();
+ } else if (d->object) {
+ QmlParser::Object *obj = 0;
+ if (d->object->defaultProperty &&
+ d->object->defaultProperty->values.count() == 1 &&
+ d->object->defaultProperty->values.at(0)->object)
+ obj = d->object->defaultProperty->values.at(0)->object;
+
+ if (obj) {
+ rv.d->object = obj;
+ rv.d->object->addref();
+ }
+ }
+
+ return rv;
+}
+
+/*!
+ Set the component's \a root object.
+*/
+void QmlDomComponent::setComponentRoot(const QmlDomObject &root)
+{
+ Q_UNUSED(root);
+ qWarning("QmlDomComponent::setComponentRoot(const QmlDomObject &): Not implemented");
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmldom.h b/src/declarative/qml/qmldom.h
new file mode 100644
index 0000000..04ce8b9
--- /dev/null
+++ b/src/declarative/qml/qmldom.h
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDOM_H
+#define QMLDOM_H
+
+#include <QtCore/qlist.h>
+#include <QtCore/qshareddata.h>
+#include <QtDeclarative/qmlerror.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QByteArray;
+class QmlDomObject;
+class QmlDomList;
+class QmlDomValue;
+class QmlEngine;
+class QmlDomComponent;
+class QIODevice;
+
+class QmlDomDocumentPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomDocument
+{
+public:
+ QmlDomDocument();
+ QmlDomDocument(const QmlDomDocument &);
+ ~QmlDomDocument();
+ QmlDomDocument &operator=(const QmlDomDocument &);
+
+ int version() const;
+ QList<QUrl> imports() const;
+
+ QList<QmlError> errors() const;
+ bool load(QmlEngine *, const QByteArray &, const QUrl & = QUrl());
+ QByteArray save() const;
+
+ QmlDomObject rootObject() const;
+private:
+ QSharedDataPointer<QmlDomDocumentPrivate> d;
+};
+
+class QmlDomPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomProperty
+{
+public:
+ QmlDomProperty();
+ QmlDomProperty(const QmlDomProperty &);
+ ~QmlDomProperty();
+ QmlDomProperty &operator=(const QmlDomProperty &);
+
+ QByteArray propertyName() const;
+ QList<QByteArray> propertyNameParts() const;
+
+ bool isDefaultProperty() const;
+
+ QmlDomValue value() const;
+ void setValue(const QmlDomValue &);
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomObject;
+ QSharedDataPointer<QmlDomPropertyPrivate> d;
+};
+
+class QmlDomObjectPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomObject
+{
+public:
+ QmlDomObject();
+ QmlDomObject(const QByteArray &);
+ QmlDomObject(const QmlDomObject &);
+ ~QmlDomObject();
+ QmlDomObject &operator=(const QmlDomObject &);
+
+ bool isValid() const;
+
+ QByteArray objectType() const;
+ QByteArray objectId() const;
+
+ void setObjectId(const QByteArray &);
+
+ QList<QmlDomProperty> properties() const;
+ QmlDomProperty property(const QByteArray &) const;
+
+ void removeProperty(const QByteArray &);
+ void addProperty(const QByteArray &, const QmlDomValue &);
+
+ bool isCustomType() const;
+ QByteArray customTypeData() const;
+ void setCustomTypeData(const QByteArray &);
+
+ bool isComponent() const;
+ QmlDomComponent toComponent() const;
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomDocument;
+ friend class QmlDomComponent;
+ friend class QmlDomValue;
+ friend class QmlDomValueValueSource;
+ QSharedDataPointer<QmlDomObjectPrivate> d;
+};
+
+class QmlDomValuePrivate;
+class QmlDomBasicValuePrivate;
+class Q_DECLARATIVE_EXPORT QmlDomValueLiteral
+{
+public:
+ QmlDomValueLiteral();
+ QmlDomValueLiteral(const QmlDomValueLiteral &);
+ ~QmlDomValueLiteral();
+ QmlDomValueLiteral &operator=(const QmlDomValueLiteral &);
+
+ QString literal() const;
+ void setLiteral(const QString &);
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValueBinding
+{
+public:
+ QmlDomValueBinding();
+ QmlDomValueBinding(const QmlDomValueBinding &);
+ ~QmlDomValueBinding();
+ QmlDomValueBinding &operator=(const QmlDomValueBinding &);
+
+ QString binding() const;
+ void setBinding(const QString &);
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValueValueSource
+{
+public:
+ QmlDomValueValueSource();
+ QmlDomValueValueSource(const QmlDomValueValueSource &);
+ ~QmlDomValueValueSource();
+ QmlDomValueValueSource &operator=(const QmlDomValueValueSource &);
+
+ QmlDomObject object() const;
+ void setObject(const QmlDomObject &);
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomComponent : public QmlDomObject
+{
+public:
+ QmlDomComponent();
+ QmlDomComponent(const QmlDomComponent &);
+ ~QmlDomComponent();
+ QmlDomComponent &operator=(const QmlDomComponent &);
+
+ QmlDomObject componentRoot() const;
+ void setComponentRoot(const QmlDomObject &);
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValue
+{
+public:
+ enum Type {
+ Invalid,
+ Literal,
+ PropertyBinding,
+ ValueSource,
+ Object,
+ List
+ };
+
+ QmlDomValue();
+ QmlDomValue(const QmlDomValue &);
+ ~QmlDomValue();
+ QmlDomValue &operator=(const QmlDomValue &);
+
+ Type type() const;
+
+ bool isInvalid() const;
+ bool isLiteral() const;
+ bool isBinding() const;
+ bool isValueSource() const;
+ bool isObject() const;
+ bool isList() const;
+
+ QmlDomValueLiteral toLiteral() const;
+ QmlDomValueBinding toBinding() const;
+ QmlDomValueValueSource toValueSource() const;
+ QmlDomObject toObject() const;
+ QmlDomList toList() const;
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomProperty;
+ friend class QmlDomList;
+ QSharedDataPointer<QmlDomValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomList
+{
+public:
+ QmlDomList();
+ QmlDomList(const QmlDomList &);
+ ~QmlDomList();
+ QmlDomList &operator=(const QmlDomList &);
+
+ QList<QmlDomValue> values() const;
+ void setValues(const QList<QmlDomValue> &);
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomValuePrivate> d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDOM_H
diff --git a/src/declarative/qml/qmldom_p.h b/src/declarative/qml/qmldom_p.h
new file mode 100644
index 0000000..74edd47
--- /dev/null
+++ b/src/declarative/qml/qmldom_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDOM_P_H
+#define QMLDOM_P_H
+
+#include <QtCore/QtGlobal>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+#include "qmlparser_p.h"
+
+class QmlDomDocumentPrivate : public QSharedData
+{
+public:
+ QmlDomDocumentPrivate();
+ QmlDomDocumentPrivate(const QmlDomDocumentPrivate &);
+ ~QmlDomDocumentPrivate();
+
+ QList<QmlError> errors;
+ QList<QUrl> imports;
+ QmlParser::Object *root;
+};
+
+class QmlDomObjectPrivate : public QSharedData
+{
+public:
+ QmlDomObjectPrivate();
+ QmlDomObjectPrivate(const QmlDomObjectPrivate &);
+ ~QmlDomObjectPrivate();
+
+ typedef QList<QPair<QmlParser::Property *, QByteArray> > Properties;
+ Properties properties() const;
+ Properties properties(QmlParser::Property *) const;
+
+ QmlParser::Object *object;
+ bool isVirtualComponent;
+};
+
+class QmlDomPropertyPrivate : public QSharedData
+{
+public:
+ QmlDomPropertyPrivate();
+ QmlDomPropertyPrivate(const QmlDomPropertyPrivate &);
+ ~QmlDomPropertyPrivate();
+
+ QByteArray propertyName;
+ QmlParser::Property *property;
+};
+
+class QmlDomValuePrivate : public QSharedData
+{
+public:
+ QmlDomValuePrivate();
+ QmlDomValuePrivate(const QmlDomValuePrivate &);
+ ~QmlDomValuePrivate();
+
+ QmlParser::Property *property;
+ QmlParser::Value *value;
+};
+
+class QmlDomBasicValuePrivate : public QSharedData
+{
+public:
+ QmlDomBasicValuePrivate();
+ QmlDomBasicValuePrivate(const QmlDomBasicValuePrivate &);
+ ~QmlDomBasicValuePrivate();
+
+ QmlParser::Value *value;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDOM_P_H
+
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
new file mode 100644
index 0000000..227aeb0
--- /dev/null
+++ b/src/declarative/qml/qmlengine.cpp
@@ -0,0 +1,1566 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QMetaProperty>
+#include <private/qmlengine_p.h>
+#include <private/qmlcontext_p.h>
+#include <private/qobject_p.h>
+
+#ifdef QT_SCRIPTTOOLS_LIB
+#include <QScriptEngineDebugger>
+#endif
+
+#include <QScriptClass>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QNetworkAccessManager>
+#include <QList>
+#include <QPair>
+#include <QDebug>
+#include <QMetaObject>
+#include "qml.h"
+#include <qfxperf.h>
+#include <QStack>
+#include "private/qmlbasicscript_p.h"
+#include "private/qmlcompiledcomponent_p.h"
+#include "qmlengine.h"
+#include "qmlcontext.h"
+#include "qmlexpression.h"
+#include <QtCore/qthreadstorage.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdir.h>
+#include <qmlcomponent.h>
+#include "private/qmlmetaproperty_p.h"
+#include <private/qmlbindablevalue_p.h>
+
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(qmlDebugger, QML_DEBUGGER);
+
+Q_DECLARE_METATYPE(QmlMetaProperty);
+
+QML_DEFINE_TYPE(QObject,Object);
+
+static QScriptValue qmlMetaProperty_emit(QScriptContext *ctx, QScriptEngine *engine)
+{
+ QmlMetaProperty mp = qscriptvalue_cast<QmlMetaProperty>(ctx->thisObject());
+ if (mp.type() & QmlMetaProperty::Signal)
+ mp.emitSignal();
+ return engine->nullValue();
+}
+
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
+};
+
+
+struct QmlEngineStack {
+ QmlEngineStack();
+
+ QStack<QmlEngine *> mainThreadEngines;
+ QThread *mainThread;
+
+ QThreadStorage<QStack<QmlEngine *> *> storage;
+
+ QStack<QmlEngine *> *engines();
+};
+
+Q_GLOBAL_STATIC(QmlEngineStack, engineStack);
+
+QmlEngineStack::QmlEngineStack()
+: mainThread(0)
+{
+}
+
+QStack<QmlEngine *> *QmlEngineStack::engines()
+{
+ if (mainThread== 0) {
+ if (!QCoreApplication::instance())
+ return 0;
+ mainThread = QCoreApplication::instance()->thread();
+ }
+
+ // Note: This is very slightly faster than just using the thread storage
+ // for everything.
+ QStack<QmlEngine *> *engines = 0;
+ if (QThread::currentThread() == mainThread) {
+ engines = &mainThreadEngines;
+ } else {
+ engines = storage.localData();
+ if (!engines) {
+ engines = new QStack<QmlEngine *>;
+ storage.setLocalData(engines);
+ }
+ }
+ return engines;
+}
+
+
+QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
+: rootContext(0), currentBindContext(0), currentExpression(0), q(e),
+ rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1)
+{
+ QScriptValue proto = scriptEngine.newObject();
+ proto.setProperty(QLatin1String("emit"),
+ scriptEngine.newFunction(qmlMetaProperty_emit));
+ scriptEngine.setDefaultPrototype(qMetaTypeId<QmlMetaProperty>(), proto);
+
+ QScriptValue qtObject = scriptEngine.newQMetaObject(StaticQtMetaObject::get());
+ scriptEngine.globalObject().setProperty(QLatin1String("Qt"), qtObject);
+}
+
+QmlEnginePrivate::~QmlEnginePrivate()
+{
+ delete rootContext;
+ rootContext = 0;
+ delete contextClass;
+ contextClass = 0;
+ delete objectClass;
+ objectClass = 0;
+ delete networkAccessManager;
+ networkAccessManager = 0;
+
+ for(int ii = 0; ii < bindValues.count(); ++ii)
+ clear(bindValues[ii]);
+ for(int ii = 0; ii < parserStatus.count(); ++ii)
+ clear(parserStatus[ii]);
+}
+
+void QmlEnginePrivate::clear(SimpleList<QmlBindableValue> &bvs)
+{
+ for (int ii = 0; ii < bvs.count; ++ii) {
+ QmlBindableValue *bv = bvs.at(ii);
+ if(bv) {
+ QmlBindableValuePrivate *p =
+ static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bv));
+ p->mePtr = 0;
+ }
+ }
+ bvs.clear();
+}
+
+void QmlEnginePrivate::clear(SimpleList<QmlParserStatus> &pss)
+{
+ for (int ii = 0; ii < pss.count; ++ii) {
+ QmlParserStatus *ps = pss.at(ii);
+ if(ps)
+ ps->d = 0;
+ }
+ pss.clear();
+}
+
+void QmlEnginePrivate::init()
+{
+ contextClass = new QmlContextScriptClass(q);
+ objectClass = new QmlObjectScriptClass(q);
+ rootContext = new QmlContext(q);
+#ifdef QT_SCRIPTTOOLS_LIB
+ if (qmlDebugger()){
+ debugger = new QScriptEngineDebugger(q);
+ debugger->attachTo(&scriptEngine);
+ }
+#endif
+}
+
+QmlContext *QmlEnginePrivate::setCurrentBindContext(QmlContext *c)
+{
+ QmlContext *old = currentBindContext;
+ currentBindContext = c;
+ return old;
+}
+
+QmlEnginePrivate::CapturedProperty::CapturedProperty(QObject *obj, int n)
+: object(obj), notifyIndex(n)
+{
+}
+
+QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p)
+: object(p.object()), name(p.name()), notifyIndex(p.property().notifySignalIndex())
+{
+}
+
+QmlEnginePrivate::CapturedProperty::CapturedProperty(const CapturedProperty &o)
+: object(o.object), name(o.name), notifyIndex(o.notifyIndex)
+{
+}
+
+QmlEnginePrivate::CapturedProperty &
+QmlEnginePrivate::CapturedProperty::operator=(const CapturedProperty &o)
+{
+ object = o.object;
+ name = o.name;
+ notifyIndex = o.notifyIndex;
+ return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache;
+Q_GLOBAL_STATIC(FunctionCache, functionCache);
+
+QScriptClass::QueryFlags
+QmlEnginePrivate::queryObject(const QString &propName,
+ uint *id, QObject *obj)
+{
+ QScriptClass::QueryFlags rv = 0;
+
+ QmlMetaProperty prop(obj, propName);
+ if (prop.type() == QmlMetaProperty::Invalid) {
+ QPair<const QMetaObject *, QString> key =
+ qMakePair(obj->metaObject(), propName);
+ bool isFunction = false;
+ if (functionCache()->contains(key)) {
+ isFunction = functionCache()->value(key);
+ } else {
+ QScriptValue sobj = scriptEngine.newQObject(obj);
+ QScriptValue func = sobj.property(propName);
+ isFunction = func.isFunction();
+ functionCache()->insert(key, isFunction);
+ }
+
+ if (isFunction) {
+ *id = QmlScriptClass::FunctionId;
+ rv |= QScriptClass::HandlesReadAccess;
+ }
+ } else {
+ *id = QmlScriptClass::PropertyId;
+ *id |= prop.save();
+
+ rv |= QScriptClass::HandlesReadAccess;
+ if (prop.isWritable())
+ rv |= QScriptClass::HandlesWriteAccess;
+ }
+
+ return rv;
+}
+
+QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName,
+ QObject *obj, uint id)
+{
+ if (id == QmlScriptClass::FunctionId) {
+ QScriptValue sobj = scriptEngine.newQObject(obj);
+ QScriptValue func = sobj.property(propName);
+ return func;
+ } else {
+ QmlMetaProperty prop;
+ prop.restore(id, obj);
+ if (!prop.isValid())
+ return QScriptValue();
+
+ if (prop.type() & QmlMetaProperty::Signal) {
+ return scriptEngine.newVariant(qVariantFromValue(prop));
+ } else {
+ QVariant var = prop.read();
+ if (prop.needsChangedNotifier())
+ capturedProperties << CapturedProperty(prop);
+ QObject *varobj = QmlMetaType::toQObject(var);
+ if (!varobj)
+ varobj = qvariant_cast<QObject *>(var);
+ if (varobj) {
+ return scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(varobj)));
+ } else {
+ if (var.type() == QVariant::Bool)
+ return QScriptValue(&scriptEngine, var.toBool());
+ return scriptEngine.newVariant(var);
+ }
+ }
+ }
+
+ return QScriptValue();
+}
+
+void QmlEnginePrivate::contextActivated(QmlContext *)
+{
+ Q_Q(QmlEngine);
+ QmlEngineStack *stack = engineStack();
+ if (!stack)
+ return;
+ QStack<QmlEngine *> *engines = stack->engines();
+ if (engines)
+ engines->push(q);
+}
+
+void QmlEnginePrivate::contextDeactivated(QmlContext *)
+{
+ QmlEngineStack *stack = engineStack();
+ if (!stack)
+ return;
+ QStack<QmlEngine *> *engines = stack->engines();
+ if (engines) {
+ Q_ASSERT(engines->top() == q_func());
+ engines->pop();
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////
+
+bool QmlEnginePrivate::fetchCache(QmlBasicScriptNodeCache &cache, const QString &propName, QObject *obj)
+{
+ QmlMetaProperty prop(obj, propName);
+
+ if (!prop.isValid())
+ return false;
+
+ if (prop.needsChangedNotifier())
+ capturedProperties << CapturedProperty(prop);
+
+ if (prop.type() & QmlMetaProperty::Attached) {
+
+ cache.object = obj;
+ cache.type = QmlBasicScriptNodeCache::Attached;
+ cache.attached = prop.d->attachedObject();
+ return true;
+
+ } else if (prop.type() & QmlMetaProperty::Property) {
+
+ cache.object = obj;
+ cache.type = QmlBasicScriptNodeCache::Core;
+ cache.core = prop.property().propertyIndex();
+ cache.coreType = prop.propertyType();
+ return true;
+
+ } else if (prop.type() & QmlMetaProperty::SignalProperty) {
+
+ cache.object = obj;
+ cache.type = QmlBasicScriptNodeCache::SignalProperty;
+ cache.core = prop.coreIndex();
+ return true;
+
+ } else if (prop.type() & QmlMetaProperty::Signal) {
+
+ cache.object = obj;
+ cache.type = QmlBasicScriptNodeCache::Signal;
+ cache.core = prop.coreIndex();
+ return true;
+
+ }
+
+ return false;
+}
+
+bool QmlEnginePrivate::loadCache(QmlBasicScriptNodeCache &cache, const QString &propName, QmlContextPrivate *context)
+{
+ while(context) {
+
+ QHash<QString, int>::ConstIterator iter =
+ context->propertyNames.find(propName);
+ if (iter != context->propertyNames.end()) {
+ cache.object = 0;
+ cache.type = QmlBasicScriptNodeCache::Variant;
+ cache.context = context;
+ cache.contextIndex = *iter;
+ capturedProperties << CapturedProperty(context->q_ptr, *iter + context->notifyIndex);
+ return true;
+ }
+
+ foreach(QObject *obj, context->defaultObjects) {
+ if (fetchCache(cache, propName, obj))
+ return true;
+ }
+
+ if (context->parent)
+ context = context->parent->d_func();
+ else
+ context = 0;
+ }
+ return false;
+}
+
+
+/*!
+ \class QmlEngine
+ \brief The QmlEngine class provides an environment for instantiating QML components.
+ \mainclass
+
+ Each QML component is instantiated in a QmlContext. QmlContext's are
+ essential for passing data to QML components. In QML, contexts are arranged
+ hierarchically and this hierarchy is managed by the QmlEngine.
+
+ Prior to creating any QML components, an application must have created a
+ QmlEngine to gain access to a QML context. The following example shows how
+ to create a simple Text item.
+
+ \code
+ QmlEngine engine;
+ QmlComponent component("Text { text: \"Hello world!\" }");
+ QFxItem *item = qobject_cast<QFxItem *>(component.create(&engine));
+
+ //add item to view, etc
+ ...
+ \endcode
+
+ In this case, the Text item will be created in the engine's
+ \l {QmlEngine::rootContext()}{root context}.
+
+ \sa QmlComponent QmlContext
+*/
+
+/*!
+ Create a new QmlEngine with the given \a parent.
+*/
+QmlEngine::QmlEngine(QObject *parent)
+: QObject(*new QmlEnginePrivate(this), parent)
+{
+ Q_D(QmlEngine);
+ d->init();
+
+ qRegisterMetaType<QVariant>("QVariant");
+}
+
+/*!
+ Destroys the QmlEngine.
+
+ Any QmlContext's created on this engine will be invalidated, but not
+ destroyed (unless they are parented to the QmlEngine object).
+*/
+QmlEngine::~QmlEngine()
+{
+}
+
+/*!
+ Clears the engine's internal component cache.
+
+ Normally the QmlEngine caches components loaded from qml files. This method
+ clears this cache and forces the component to be reloaded.
+ */
+void QmlEngine::clearComponentCache()
+{
+ Q_D(QmlEngine);
+ d->typeManager.clearCache();
+}
+
+/*!
+ Returns the engine's root context.
+
+ The root context is automatically created by the QmlEngine. Data that
+ should be available to all QML component instances instantiated by the
+ engine should be put in the root context.
+
+ Additional data that should only be available to a subset of component
+ instances should be added to sub-contexts parented to the root context.
+*/
+QmlContext *QmlEngine::rootContext()
+{
+ Q_D(QmlEngine);
+ return d->rootContext;
+}
+
+/*!
+ Returns this engine's active context, or 0 if no context is active on this
+ engine.
+
+ Contexts are activated and deactivated by calling QmlContext::activate() and
+ QmlContext::deactivate() respectively.
+
+ Context activation holds no special semantic, other than it allows types
+ instantiated by QML to access "their" context without having it passed as
+ a parameter in their constructor, as shown below.
+ \code
+ class MyClass : ... {
+ ...
+ MyClass() {
+ qWarning() << "I was instantiated in this context:"
+ << QmlContext::activeContext();
+ }
+ };
+ \endcode
+*/
+QmlContext *QmlEngine::activeContext()
+{
+ Q_D(QmlEngine);
+ if (d->currentBindContext)
+ return d->currentBindContext;
+ else
+ return 0;
+}
+
+/*!
+ Sets the mappings from namespace URIs to URL to \a map.
+
+ \sa nameSpacePaths()
+*/
+void QmlEngine::setNameSpacePaths(const QMap<QString,QString>& map)
+{
+ Q_D(QmlEngine);
+ d->nameSpacePaths = map;
+}
+
+/*!
+ Adds mappings (given by \a map) from namespace URIs to URL.
+
+ \sa nameSpacePaths()
+*/
+void QmlEngine::addNameSpacePaths(const QMap<QString,QString>& map)
+{
+ Q_D(QmlEngine);
+ d->nameSpacePaths.unite(map);
+}
+
+/*!
+ Adds a mapping from namespace URI \a ns to URL \a path.
+
+ \sa nameSpacePaths()
+*/
+void QmlEngine::addNameSpacePath(const QString& ns, const QString& path)
+{
+ Q_D(QmlEngine);
+ d->nameSpacePaths.insertMulti(ns,path);
+}
+
+/*!
+ Returns the mapping from namespace URIs to URLs.
+
+ Currently, only the empty namespace is supported
+ (i.e. types cannot be qualified with a namespace).
+
+ The QML \c import statement can be used to import a directory of
+ components into the empty namespace.
+
+ \qml
+ import "MyModuleDirectory"
+ \endqml
+
+ This is also possible from C++:
+
+ \code
+ engine->addNameSpacePath("","file:///opt/abcdef");
+ \endcode
+
+ \sa componentUrl()
+*/
+QMap<QString,QString> QmlEngine::nameSpacePaths() const
+{
+ Q_D(const QmlEngine);
+ return d->nameSpacePaths;
+}
+
+/*!
+ Returns the URL for the component source \a src, as mapped
+ by the nameSpacePaths(), resolved relative to \a baseUrl.
+
+ \sa nameSpacePaths()
+*/
+QUrl QmlEngine::componentUrl(const QUrl& src, const QUrl& baseUrl) const
+{
+ Q_D(const QmlEngine);
+
+ // Find the most-specific namespace matching src.
+ // For files, multiple paths can be given, the first found is used.
+ QUrl r;
+ QMap<QString, QString>::const_iterator i = d->nameSpacePaths.constBegin();
+ QString rns=QLatin1String(":"); // ns of r, if file found, initial an imposible namespace
+ QString srcstring = src.toString();
+ while (i != d->nameSpacePaths.constEnd()) {
+ QString ns = i.key();
+ QString path = i.value();
+ if (ns != rns) {
+ if (srcstring.startsWith(ns) && (ns.length()==0 || srcstring[ns.length()]==QLatin1Char('/'))) {
+ QString file = ns.length()==0 ? srcstring : srcstring.mid(ns.length()+1);
+ QUrl cr = baseUrl.resolved(QUrl(path + QLatin1String("/") + file));
+ QString lf = cr.toLocalFile();
+ if (lf.isEmpty() || QFile::exists(lf)) {
+ r = cr;
+ rns = ns;
+ }
+ }
+ }
+ ++i;
+ }
+ if (r.isEmpty())
+ r = baseUrl.resolved(src);
+ return r;
+}
+
+/*!
+ Sets the common QNetworkAccessManager, \a network, used by all QML elements instantiated
+ by this engine.
+
+ Any previously set manager is deleted and \a network is owned by the QmlEngine. This
+ method should only be called before any QmlComponents are instantiated.
+*/
+void QmlEngine::setNetworkAccessManager(QNetworkAccessManager *network)
+{
+ Q_D(QmlEngine);
+ delete d->networkAccessManager;
+ d->networkAccessManager = network;
+}
+
+/*!
+ Returns the common QNetworkAccessManager used by all QML elements
+ instantiated by this engine.
+
+ The default implements no caching, cookiejar, etc., just a default
+ QNetworkAccessManager.
+*/
+QNetworkAccessManager *QmlEngine::networkAccessManager() const
+{
+ Q_D(const QmlEngine);
+ if (!d->networkAccessManager)
+ d->networkAccessManager = new QNetworkAccessManager;
+ return d->networkAccessManager;
+}
+
+/*!
+ Returns the QmlContext for the \a object, or 0 if no context has been set.
+
+ When the QmlEngine instantiates a QObject, the context is set automatically.
+ */
+QmlContext *QmlEngine::contextForObject(const QObject *object)
+{
+ if(!object)
+ return 0;
+
+ QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
+
+ QmlSimpleDeclarativeData *data =
+ static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData);
+
+ return data?data->context:0;
+}
+
+/*!
+ Sets the QmlContext for the \a object to \a context.
+ If the \a object already has a context, a warning is
+ output, but the context is not changed.
+
+ When the QmlEngine instantiates a QObject, the context is set automatically.
+ */
+void QmlEngine::setContextForObject(QObject *object, QmlContext *context)
+{
+ QObjectPrivate *priv = QObjectPrivate::get(object);
+
+ QmlSimpleDeclarativeData *data =
+ static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData);
+
+ if (data && data->context) {
+ qWarning("QmlEngine::setContextForObject(): Object already has a QmlContext");
+ return;
+ }
+
+ if (!data) {
+ priv->declarativeData = &context->d_func()->contextData;
+ } else {
+ data->context = context;
+ }
+
+ context->d_func()->contextObjects.append(object);
+}
+
+QmlContext *qmlContext(const QObject *obj)
+{
+ return QmlEngine::contextForObject(obj);
+}
+
+QmlEngine *qmlEngine(const QObject *obj)
+{
+ QmlContext *context = QmlEngine::contextForObject(obj);
+ return context?context->engine():0;
+}
+
+QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object)
+{
+ QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
+
+
+ QmlSimpleDeclarativeData *data = static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData);
+
+ QmlExtendedDeclarativeData *edata = (data && data->flags & QmlSimpleDeclarativeData::Extended)?static_cast<QmlExtendedDeclarativeData *>(data):0;
+
+ if (edata) {
+ QObject *rv = edata->attachedProperties.value(id);
+ if (rv)
+ return rv;
+ }
+
+ QmlAttachedPropertiesFunc pf = QmlMetaType::attachedPropertiesFuncById(id);
+ if (!pf)
+ return 0;
+
+ QObject *rv = pf(const_cast<QObject *>(object));
+
+ if (rv) {
+ if (!edata) {
+
+ edata = new QmlExtendedDeclarativeData;
+ if (data) edata->context = data->context;
+ priv->declarativeData = edata;
+
+ }
+
+ edata->attachedProperties.insert(id, rv);
+ }
+
+ return rv;
+}
+
+void QmlSimpleDeclarativeData::destroyed(QObject *object)
+{
+ if (context)
+ context->d_func()->contextObjects.removeAll(object);
+}
+
+void QmlExtendedDeclarativeData::destroyed(QObject *object)
+{
+ QmlSimpleDeclarativeData::destroyed(object);
+ delete this;
+}
+
+/*! \internal */
+QScriptEngine *QmlEngine::scriptEngine()
+{
+ Q_D(QmlEngine);
+ return &d->scriptEngine;
+}
+
+/*!
+ Returns the currently active QmlEngine.
+
+ The active engine is the engine associated with the last activated
+ QmlContext. This method is thread-safe - the "active" engine is maintained
+ independently for each thread.
+*/
+QmlEngine *QmlEngine::activeEngine()
+{
+ QmlEngineStack *stack = engineStack();
+ if (!stack) return 0;
+
+ QStack<QmlEngine *> *engines = stack->engines();
+ if (!engines) {
+ qWarning("QmlEngine::activeEngine() cannot be called before the construction of QCoreApplication");
+ return 0;
+ }
+
+ if (engines->isEmpty())
+ return 0;
+ else
+ return engines->top();
+}
+
+
+
+QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b)
+: q(b), ctxt(0), sseData(0), proxy(0), me(0), trackChange(false), id(0), log(0)
+{
+}
+
+QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, void *expr, QmlRefCount *rc)
+: q(b), ctxt(0), sse((const char *)expr, rc), sseData(0), proxy(0), me(0), trackChange(true), id(0), log(0)
+{
+}
+
+QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, const QString &expr, bool ssecompile)
+: q(b), ctxt(0), expression(expr), sseData(0), proxy(0), me(0), trackChange(true), id(0), log(0)
+{
+ if (ssecompile) {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindCompile> pt;
+#endif
+ sse.compile(expr.toLatin1());
+ }
+}
+
+QmlExpressionPrivate::~QmlExpressionPrivate()
+{
+ sse.deleteScriptState(sseData);
+ sseData = 0;
+ delete proxy;
+ delete log;
+}
+
+/*!
+ Create an invalid QmlExpression.
+
+ As the expression will not have an associated QmlContext, this will be a
+ null expression object and its value will always be an invalid QVariant.
+ */
+QmlExpression::QmlExpression()
+: d(new QmlExpressionPrivate(this))
+{
+}
+
+/*! \internal */
+QmlExpression::QmlExpression(QmlContext *ctxt, void *expr,
+ QmlRefCount *rc, QObject *me)
+: d(new QmlExpressionPrivate(this, expr, rc))
+{
+ d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
+ if(ctxt)
+ ctxt->d_func()->childExpressions.insert(this);
+ d->me = me;
+}
+
+/*! \internal */
+QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expr,
+ QObject *me, bool ssecompile)
+: d(new QmlExpressionPrivate(this, expr, ssecompile))
+{
+ d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
+ if(ctxt)
+ ctxt->d_func()->childExpressions.insert(this);
+ d->me = me;
+}
+
+/*!
+ Create a QmlExpression object.
+
+ The \a expression ECMAScript will be executed in the \a ctxt QmlContext.
+ If specified, the \a scope object's properties will also be in scope during
+ the expression's execution.
+*/
+QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression,
+ QObject *scope)
+: d(new QmlExpressionPrivate(this, expression, true))
+{
+ d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
+ if(ctxt)
+ ctxt->d_func()->childExpressions.insert(this);
+ d->me = scope;
+}
+
+/*!
+ Destroy the QmlExpression instance.
+*/
+QmlExpression::~QmlExpression()
+{
+ if (d->ctxt)
+ d->ctxt->d_func()->childExpressions.remove(this);
+ delete d; d = 0;
+}
+
+/*!
+ Returns the QmlEngine this expression is associated with, or 0 if there
+ is no association or the QmlEngine has been destroyed.
+*/
+QmlEngine *QmlExpression::engine() const
+{
+ return d->ctxt?d->ctxt->engine():0;
+}
+
+/*!
+ Returns the QmlContext this expression is associated with, or 0 if there
+ is no association or the QmlContext has been destroyed.
+*/
+QmlContext *QmlExpression::context() const
+{
+ return d->ctxt;
+}
+
+/*!
+ Returns the expression string.
+*/
+QString QmlExpression::expression() const
+{
+ if (d->sse.isValid())
+ return QLatin1String(d->sse.expression());
+ else
+ return d->expression;
+}
+
+/*!
+ Clear the expression.
+*/
+void QmlExpression::clearExpression()
+{
+ setExpression(QString());
+}
+
+/*!
+ Set the expression to \a expression.
+*/
+void QmlExpression::setExpression(const QString &expression)
+{
+ if (d->sseData) {
+ d->sse.deleteScriptState(d->sseData);
+ d->sseData = 0;
+ }
+
+ delete d->proxy; d->proxy = 0;
+
+ d->expression = expression;
+
+ if (d->expression.isEmpty())
+ d->sse.clear();
+ else
+ d->sse.compile(expression.toLatin1());
+}
+
+/*!
+ Called by QmlExpression each time the expression value changes from the
+ last time it was evaluated. The expression must have been evaluated at
+ least once (by calling QmlExpression::value()) before this callback will
+ be made.
+
+ The default implementation does nothing.
+*/
+void QmlExpression::valueChanged()
+{
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+void BindExpressionProxy::changed()
+{
+ e->valueChanged();
+}
+
+/*!
+ Returns the value of the expression, or an invalid QVariant if the
+ expression is invalid or has an error.
+*/
+QVariant QmlExpression::value()
+{
+ QVariant rv;
+ if (!d->ctxt || !engine() || (!d->sse.isValid() && d->expression.isEmpty()))
+ return rv;
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindValue> perf;
+#endif
+
+ QmlBasicScript::CacheState cacheState = QmlBasicScript::Reset;
+
+ QmlEnginePrivate *ep = engine()->d_func();
+ QmlExpression *lastCurrentExpression = ep->currentExpression;
+ ep->currentExpression = this;
+ if (d->sse.isValid()) {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindValueSSE> perfsse;
+#endif
+
+ context()->d_func()->defaultObjects.insert(context()->d_func()->highPriorityCount, d->me);
+
+ if (!d->sseData)
+ d->sseData = d->sse.newScriptState();
+ rv = d->sse.run(context(), d->sseData, &cacheState);
+
+ context()->d_func()->defaultObjects.removeAt(context()->d_func()->highPriorityCount);
+ } else {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindValueQt> perfqt;
+#endif
+ context()->d_func()->defaultObjects.insert(context()->d_func()->highPriorityCount, d->me);
+
+ QScriptEngine *scriptEngine = engine()->scriptEngine();
+ QScriptValueList oldScopeChain = scriptEngine->currentContext()->scopeChain();
+ for (int i = 0; i < oldScopeChain.size(); ++i) {
+ scriptEngine->currentContext()->popScope();
+ }
+ for (int i = context()->d_func()->scopeChain.size() - 1; i > -1; --i) {
+ scriptEngine->currentContext()->pushScope(context()->d_func()->scopeChain.at(i));
+ }
+ QScriptValue svalue = scriptEngine->evaluate(expression());
+ if (scriptEngine->hasUncaughtException()) {
+ if (scriptEngine->uncaughtException().isError()){
+ QScriptValue exception = scriptEngine->uncaughtException();
+ if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){
+ qWarning() << exception.property(QLatin1String("fileName")).toString()
+ << scriptEngine->uncaughtExceptionLineNumber()
+ << exception.toString();
+
+ } else {
+ qWarning() << exception.toString();
+ }
+ }
+ }
+
+ context()->d_func()->defaultObjects.removeAt(context()->d_func()->highPriorityCount);
+ if (svalue.isArray()) {
+ int length = svalue.property(QLatin1String("length")).toInt32();
+ if (length && svalue.property(0).isObject()) {
+ QList<QObject *> list;
+ for (int ii = 0; ii < length; ++ii) {
+ QScriptValue arrayItem = svalue.property(ii);
+ QObject *d = qvariant_cast<QObject *>(arrayItem.data().toVariant());
+ if (d) {
+ list << d;
+ } else {
+ list << 0;
+ }
+ }
+ rv = QVariant::fromValue(list);
+ }
+ } /*else if (svalue.isVariant()) {
+ rv = svalue.toVariant();
+ }*/ else if (svalue.isObject()) {
+ QScriptValue objValue = svalue.data();
+ if (objValue.isValid())
+ rv = objValue.toVariant();
+ }
+ if (rv.isNull()) {
+ rv = svalue.toVariant();
+ }
+
+ for (int i = 0; i < context()->d_func()->scopeChain.size(); ++i) {
+ scriptEngine->currentContext()->popScope();
+ }
+ for (int i = oldScopeChain.size() - 1; i > -1; --i) {
+ scriptEngine->currentContext()->pushScope(oldScopeChain.at(i));
+ }
+ }
+ ep->currentExpression = lastCurrentExpression;
+
+ if (cacheState != QmlBasicScript::NoChange) {
+ if (cacheState != QmlBasicScript::Incremental && d->proxy) {
+ delete d->proxy;
+ d->proxy = 0;
+ }
+
+ if (trackChange() && ep->capturedProperties.count()) {
+ if (!d->proxy)
+ d->proxy = new BindExpressionProxy(this);
+
+ static int changedIndex = -1;
+ if (changedIndex == -1)
+ changedIndex = BindExpressionProxy::staticMetaObject.indexOfSlot("changed()");
+
+ if(qmlDebugger()) {
+ QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
+ log.setExpression(expression());
+ log.setResult(rv);
+
+ for (int ii = 0; ii < ep->capturedProperties.count(); ++ii) {
+ const QmlEnginePrivate::CapturedProperty &prop =
+ ep->capturedProperties.at(ii);
+
+ if (prop.notifyIndex != -1) {
+ QMetaObject::connect(prop.object, prop.notifyIndex,
+ d->proxy, changedIndex);
+ } else {
+ QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: [") + QLatin1String(prop.object->metaObject()->className()) + QLatin1String("].") + prop.name;
+ log.addWarning(warn);
+ }
+ }
+ d->addLog(log);
+
+ } else {
+ for (int ii = 0; ii < ep->capturedProperties.count(); ++ii) {
+ const QmlEnginePrivate::CapturedProperty &prop =
+ ep->capturedProperties.at(ii);
+
+ if (prop.notifyIndex != -1)
+ QMetaObject::connect(prop.object, prop.notifyIndex,
+ d->proxy, changedIndex);
+ }
+ }
+ } else {
+ QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
+ log.setExpression(expression());
+ log.setResult(rv);
+ d->addLog(log);
+ }
+
+ } else {
+ if(qmlDebugger()) {
+ QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
+ log.setExpression(expression());
+ log.setResult(rv);
+ d->addLog(log);
+ }
+ }
+
+ ep->capturedProperties.clear();
+
+ return rv;
+}
+
+/*!
+ Returns true if the expression results in a constant value.
+ QmlExpression::value() must have been invoked at least once before the
+ return from this method is valid.
+ */
+bool QmlExpression::isConstant() const
+{
+ return d->proxy == 0;
+}
+
+/*!
+ Returns true if the changes are tracked in the expression's value.
+*/
+bool QmlExpression::trackChange() const
+{
+ return d->trackChange;
+}
+
+/*!
+ Set whether changes are tracked in the expression's value to \a trackChange.
+
+ If true, the QmlExpression will monitor properties involved in the
+ expression's evaluation, and call QmlExpression::valueChanged() if they have
+ changed. This allows an application to ensure that any value associated
+ with the result of the expression remains up to date.
+
+ If false, the QmlExpression will not montitor properties involved in the
+ expression's evaluation, and QmlExpression::valueChanged() will never be
+ called. This is more efficient if an application wants a "one off"
+ evaluation of the expression.
+
+ By default, trackChange is true.
+*/
+void QmlExpression::setTrackChange(bool trackChange)
+{
+ d->trackChange = trackChange;
+}
+
+/*!
+ Returns the expression's scope object, if provided, otherwise 0.
+
+ In addition to data provided by the expression's QmlContext, the scope
+ object's properties are also in scope during the expression's evaluation.
+*/
+QObject *QmlExpression::scopeObject() const
+{
+ return d->me;
+}
+
+/*!
+ \internal
+*/
+quint32 QmlExpression::id() const
+{
+ return d->id;
+}
+
+/*!
+ \class QmlExpression
+ \brief The QmlExpression class evaluates ECMAScript in a QML context.
+*/
+
+/*!
+ \class QmlExpressionObject
+ \brief The QmlExpressionObject class extends QmlExpression with signals and slots.
+
+ To remain as lightweight as possible, QmlExpression does not inherit QObject
+ and consequently cannot use signals or slots. For the cases where this is
+ more convenient in an application, QmlExpressionObject can be used instead.
+
+ QmlExpressionObject behaves identically to QmlExpression, except that the
+ QmlExpressionObject::value() method is a slot, and the
+ QmlExpressionObject::valueChanged() callback is a signal.
+*/
+/*!
+ Create a QmlExpression with the specified \a parent.
+
+ As the expression will not have an associated QmlContext, this will be a
+ null expression object and its value will always be an invalid QVariant.
+*/
+QmlExpressionObject::QmlExpressionObject(QObject *parent)
+: QObject(parent)
+{
+}
+
+/*!
+ Create a QmlExpressionObject with the specified \a parent.
+
+ The \a expression ECMAScript will be executed in the \a ctxt QmlContext.
+ If specified, the \a scope object's properties will also be in scope during
+ the expression's execution.
+*/
+QmlExpressionObject::QmlExpressionObject(QmlContext *ctxt, const QString &expression, QObject *scope, QObject *parent)
+: QObject(parent), QmlExpression(ctxt, expression, scope, true)
+{
+}
+
+/*! \internal */
+QmlExpressionObject::QmlExpressionObject(QmlContext *ctxt, const QString &expr, QObject *scope, bool sse)
+: QmlExpression(ctxt, expr, scope, sse)
+{
+}
+
+/*! \internal */
+QmlExpressionObject::QmlExpressionObject(QmlContext *ctxt, void *d, QmlRefCount *rc, QObject *me)
+: QmlExpression(ctxt, d, rc, me)
+{
+}
+
+/*!
+ Returns the value of the expression, or an invalid QVariant if the
+ expression is invalid or has an error.
+*/
+QVariant QmlExpressionObject::value()
+{
+ return QmlExpression::value();
+}
+
+/*!
+ \fn void QmlExpressionObject::valueChanged()
+
+ Emitted each time the expression value changes from the last time it was
+ evaluated. The expression must have been evaluated at least once (by
+ calling QmlExpressionObject::value()) before this signal will be emitted.
+*/
+
+QmlScriptClass::QmlScriptClass(QmlEngine *bindengine)
+: QScriptClass(bindengine->scriptEngine()), engine(bindengine)
+{
+}
+
+/////////////////////////////////////////////////////////////
+/*
+ The QmlContextScriptClass handles property access for a QmlContext
+ via QtScript.
+ */
+QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine)
+ : QmlScriptClass(bindEngine)
+{
+}
+
+QmlContextScriptClass::~QmlContextScriptClass()
+{
+}
+
+QScriptClass::QueryFlags
+QmlContextScriptClass::queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id)
+{
+ Q_UNUSED(flags);
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ContextQuery> perf;
+#endif
+ QmlContext *bindContext =
+ static_cast<QmlContext*>(object.data().toQObject());
+ QueryFlags rv = 0;
+
+ QString propName = name.toString();
+
+#ifdef PROPERTY_DEBUG
+ qWarning() << "Query Context:" << propName << bindContext;
+#endif
+
+ *id = InvalidId;
+ if (bindContext->d_func()->propertyNames.contains(propName)) {
+ rv |= HandlesReadAccess;
+ *id = VariantPropertyId;
+ }
+
+ for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) {
+ rv = engine->d_func()->queryObject(propName, id,
+ bindContext->d_func()->defaultObjects.at(ii));
+ if (rv)
+ *id |= (ii << 24);
+ }
+
+ return rv;
+}
+
+QScriptValue QmlContextScriptClass::property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ContextProperty> perf;
+#endif
+ QmlContext *bindContext =
+ static_cast<QmlContext*>(object.data().toQObject());
+
+#ifdef PROPERTY_DEBUG
+ QString propName = name.toString();
+ qWarning() << "Context Property:" << propName << bindContext;
+#endif
+
+ uint basicId = id & QmlScriptClass::ClassIdMask;
+
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+
+ switch (basicId) {
+ case VariantPropertyId:
+ {
+ QString propName = name.toString();
+ int index = bindContext->d_func()->propertyNames.value(propName);
+ QVariant value = bindContext->d_func()->propertyValues.at(index);
+#ifdef PROPERTY_DEBUG
+ qWarning() << "Context Property: Resolved property" << propName
+ << "to context variant property list" << bindContext <<". Value:" << rv.toVariant();
+#endif
+ QScriptValue rv;
+ if (QmlMetaType::isObject(value.userType())) {
+ rv = scriptEngine->newObject(engine->d_func()->objectClass, scriptEngine->newVariant(value));
+ } else {
+ rv = scriptEngine->newVariant(value);
+ }
+ engine->d_func()->capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, index + bindContext->d_func()->notifyIndex);
+ return rv;
+ }
+ default:
+ {
+ int objId = (id & ClassIdSelectorMask) >> 24;
+ QObject *obj = bindContext->d_func()->defaultObjects.at(objId);
+ QScriptValue rv = engine->d_func()->propertyObject(name, obj,
+ id & ~QmlScriptClass::ClassIdSelectorMask);
+ if (rv.isValid()) {
+#ifdef PROPERTY_DEBUG
+ qWarning() << "~Property: Resolved property" << propName
+ << "to context default object" << bindContext << obj <<". Value:" << rv.toVariant();
+#endif
+ return rv;
+ }
+ break;
+ }
+ }
+
+ return QScriptValue();
+}
+
+void QmlContextScriptClass::setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value)
+{
+ Q_UNUSED(name);
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ObjectSetProperty> perf;
+#endif
+ QmlContext *bindContext =
+ static_cast<QmlContext*>(object.data().toQObject());
+
+#ifdef PROPERTY_DEBUG
+ QString propName = name.toString();
+ qWarning() << "Set QmlObject Property" << name.toString() << value.toVariant();
+#endif
+
+ int objIdx = (id & QmlScriptClass::ClassIdSelectorMask) >> 24;
+ QObject *obj = bindContext->d_func()->defaultObjects.at(objIdx);
+
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+ QScriptValue oldact = scriptEngine->currentContext()->activationObject();
+ scriptEngine->currentContext()->setActivationObject(scriptEngine->globalObject());
+
+ QmlMetaProperty prop;
+ prop.restore(id, obj);
+
+ QVariant v;
+ QObject *data = value.data().toQObject();
+ if (data) {
+ v = QVariant::fromValue(data);
+ } else {
+ v = value.toVariant();
+ }
+ prop.write(v);
+
+ scriptEngine->currentContext()->setActivationObject(oldact);
+}
+
+/////////////////////////////////////////////////////////////
+/*
+ The QmlObjectScriptClass handles property access for QObjects
+ via QtScript.
+ */
+QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine)
+ : QmlScriptClass(bindEngine)
+{
+ engine = bindEngine;
+}
+
+QmlObjectScriptClass::~QmlObjectScriptClass()
+{
+}
+
+QScriptClass::QueryFlags QmlObjectScriptClass::queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id)
+{
+ Q_UNUSED(flags);
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ObjectQuery> perf;
+#endif
+ QObject *obj = object.data().toQObject();
+ QueryFlags rv = 0;
+ QString propName = name.toString();
+
+#ifdef PROPERTY_DEBUG
+ qWarning() << "Query QmlObject:" << propName << obj;
+#endif
+
+ if (obj)
+ rv = engine->d_func()->queryObject(propName, id, obj);
+
+ return rv;
+}
+
+QScriptValue QmlObjectScriptClass::property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ObjectProperty> perf;
+#endif
+ QObject *obj = object.data().toQObject();
+
+#ifdef PROPERTY_DEBUG
+ QString propName = name.toString();
+ qWarning() << "QmlObject Property:" << propName << obj;
+#endif
+
+ QScriptValue rv = engine->d_func()->propertyObject(name, obj, id);
+ if (rv.isValid()) {
+#ifdef PROPERTY_DEBUG
+ qWarning() << "~Property: Resolved property" << propName
+ << "to object" << obj <<". Value:" << rv.toVariant();
+#endif
+ return rv;
+ }
+
+ return QScriptValue();
+}
+
+void QmlObjectScriptClass::setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value)
+{
+ Q_UNUSED(name);
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ObjectSetProperty> perf;
+#endif
+ QObject *obj = object.data().toQObject();
+
+#ifdef PROPERTY_DEBUG
+ QString propName = name.toString();
+ qWarning() << "Set QmlObject Property" << name.toString() << value.toVariant();
+#endif
+
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+ QScriptValue oldact = scriptEngine->currentContext()->activationObject();
+ scriptEngine->currentContext()->setActivationObject(scriptEngine->globalObject());
+
+ QmlMetaProperty prop;
+ prop.restore(id, obj);
+
+ QVariant v;
+ QObject *data = value.data().toQObject();
+ if (data) {
+ v = QVariant::fromValue(data);
+ } else {
+ v = value.toVariant();
+ }
+ prop.write(v);
+
+ scriptEngine->currentContext()->setActivationObject(oldact);
+}
+
+void QmlExpressionPrivate::addLog(const QmlExpressionLog &l)
+{
+ if (!log)
+ log = new QList<QmlExpressionLog>();
+ log->append(l);
+}
+
+QmlExpressionLog::QmlExpressionLog()
+{
+}
+
+QmlExpressionLog::QmlExpressionLog(const QmlExpressionLog &o)
+: m_time(o.m_time),
+ m_expression(o.m_expression),
+ m_result(o.m_result),
+ m_warnings(o.m_warnings)
+{
+}
+
+QmlExpressionLog::~QmlExpressionLog()
+{
+}
+
+QmlExpressionLog &QmlExpressionLog::operator=(const QmlExpressionLog &o)
+{
+ m_time = o.m_time;
+ m_expression = o.m_expression;
+ m_result = o.m_result;
+ m_warnings = o.m_warnings;
+ return *this;
+}
+
+void QmlExpressionLog::setTime(quint32 time)
+{
+ m_time = time;
+}
+
+quint32 QmlExpressionLog::time() const
+{
+ return m_time;
+}
+
+QString QmlExpressionLog::expression() const
+{
+ return m_expression;
+}
+
+void QmlExpressionLog::setExpression(const QString &e)
+{
+ m_expression = e;
+}
+
+QStringList QmlExpressionLog::warnings() const
+{
+ return m_warnings;
+}
+
+void QmlExpressionLog::addWarning(const QString &w)
+{
+ m_warnings << w;
+}
+
+QVariant QmlExpressionLog::result() const
+{
+ return m_result;
+}
+
+void QmlExpressionLog::setResult(const QVariant &r)
+{
+ m_result = r;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h
new file mode 100644
index 0000000..fde84d4
--- /dev/null
+++ b/src/declarative/qml/qmlengine.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLENGINE_H
+#define QMLENGINE_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmap.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlComponent;
+class QmlEnginePrivate;
+class QmlExpression;
+class QmlContext;
+class QUrl;
+class QScriptEngine;
+class QNetworkAccessManager;
+class Q_DECLARATIVE_EXPORT QmlEngine : public QObject
+{
+ Q_OBJECT
+public:
+ QmlEngine(QObject *p = 0);
+ virtual ~QmlEngine();
+
+ static QmlEngine *activeEngine();
+
+ QmlContext *rootContext();
+ QmlContext *activeContext();
+
+ void clearComponentCache();
+
+ void setNameSpacePaths(const QMap<QString,QString>& map);
+ void addNameSpacePaths(const QMap<QString,QString>& map);
+ void addNameSpacePath(const QString&,const QString&);
+ QMap<QString,QString> nameSpacePaths() const;
+ QUrl componentUrl(const QUrl& src, const QUrl& baseUrl) const;
+
+ void setNetworkAccessManager(QNetworkAccessManager *);
+ QNetworkAccessManager *networkAccessManager() const;
+
+ static QmlContext *contextForObject(const QObject *);
+ static void setContextForObject(QObject *, QmlContext *);
+private:
+ // LK: move to the private class
+ QScriptEngine *scriptEngine();
+ friend class QFxItem; // XXX
+ friend class QmlScriptPrivate;
+ friend class QmlCompositeTypeManager;
+ friend class QmlCompiler;
+ friend class QmlScriptClass;
+ friend class QmlContext;
+ friend class QmlContextPrivate;
+ friend class QmlExpression;
+ friend class QmlBasicScript;
+ friend class QmlVME;
+ friend class QmlComponent;
+ friend class QmlContextScriptClass; //###
+ friend class QmlObjectScriptClass; //###
+ Q_DECLARE_PRIVATE(QmlEngine)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLENGINE_H
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
new file mode 100644
index 0000000..7578fdf
--- /dev/null
+++ b/src/declarative/qml/qmlengine_p.h
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLENGINE_P_H
+#define QMLENGINE_P_H
+
+#include <QScriptClass>
+#include <QScriptValue>
+#include <QScriptString>
+#include <QtCore/qstring.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qstack.h>
+#include <private/qobject_p.h>
+#include <private/qmlclassfactory_p.h>
+#include <private/qmlcompositetypemanager_p.h>
+#include <qml.h>
+#include <qmlbasicscript.h>
+#include <qmlcontext.h>
+#include <qmlengine.h>
+#include <qmlexpression.h>
+#include <QtScript/qscriptengine.h>
+
+QT_BEGIN_NAMESPACE
+class QmlContext;
+class QmlEngine;
+class QmlContextPrivate;
+class QmlExpression;
+class QmlBasicScriptNodeCache;
+class QmlContextScriptClass;
+class QmlObjectScriptClass;
+class QScriptEngineDebugger;
+class QNetworkReply;
+class QNetworkAccessManager;
+
+class QmlEnginePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlEngine)
+public:
+ QmlEnginePrivate(QmlEngine *);
+ ~QmlEnginePrivate();
+
+ void init();
+
+ void contextActivated(QmlContext *);
+ void contextDeactivated(QmlContext *);
+
+ bool fetchCache(QmlBasicScriptNodeCache &cache, const QString &propName, QObject *);
+ bool loadCache(QmlBasicScriptNodeCache &cache, const QString &propName, QmlContextPrivate *context);
+
+ QScriptClass::QueryFlags queryObject(const QString &name, uint *id, QObject *);
+ QScriptValue propertyObject(const QScriptString &propName, QObject *, uint id = 0);
+
+ struct CapturedProperty {
+ CapturedProperty(QObject *, int);
+ CapturedProperty(const QmlMetaProperty &);
+ CapturedProperty(const CapturedProperty &);
+ CapturedProperty &operator=(const CapturedProperty &);
+
+ QObject *object;
+ QString name;
+ int notifyIndex;
+ };
+ QList<CapturedProperty> capturedProperties;
+
+ QmlContext *rootContext;
+ QmlContext *currentBindContext;
+ QmlExpression *currentExpression;
+ QmlEngine *q;
+#ifdef QT_SCRIPTTOOLS_LIB
+ QScriptEngineDebugger *debugger;
+#endif
+
+ QmlContextScriptClass *contextClass;
+ QmlObjectScriptClass *objectClass;
+
+ QmlContext *setCurrentBindContext(QmlContext *);
+ QStack<QmlContext *> activeContexts;
+
+ QScriptEngine scriptEngine;
+
+ template<class T>
+ struct SimpleList {
+ SimpleList()
+ : count(0), values(0) {}
+ SimpleList(int r)
+ : count(0), values(new T*[r]) {}
+
+ int count;
+ T **values;
+
+ void append(T *v) {
+ values[count++] = v;
+ }
+
+ T *at(int idx) const {
+ return values[idx];
+ }
+
+ void clear() {
+ delete [] values;
+ }
+ };
+
+ static void clear(SimpleList<QmlBindableValue> &);
+ static void clear(SimpleList<QmlParserStatus> &);
+
+ QList<SimpleList<QmlBindableValue> > bindValues;
+ QList<SimpleList<QmlParserStatus> > parserStatus;
+
+ QmlComponent *rootComponent;
+ mutable QNetworkAccessManager *networkAccessManager;
+
+ QmlCompositeTypeManager typeManager;
+ QMap<QString,QString> nameSpacePaths;
+
+ mutable quint32 uniqueId;
+ quint32 getUniqueId() const {
+ return uniqueId++;
+ }
+};
+
+
+class BindExpressionProxy : public QObject
+{
+Q_OBJECT
+public:
+ BindExpressionProxy(QmlExpression *be)
+ :e(be)
+ {
+ }
+
+private:
+ QmlExpression *e;
+
+private Q_SLOTS:
+ void changed();
+};
+
+class QmlScriptClass : public QScriptClass
+{
+public:
+ enum ClassId
+ {
+ InvalidId = -1,
+
+ FunctionId = 0x80000000,
+ VariantPropertyId = 0x40000000,
+ PropertyId = 0x00000000,
+
+ ClassIdMask = 0xC0000000,
+
+ ClassIdSelectorMask = 0x3F000000,
+ };
+
+ QmlScriptClass(QmlEngine *);
+
+protected:
+ QmlEngine *engine;
+};
+
+class QmlContextScriptClass : public QmlScriptClass
+{
+public:
+ QmlContextScriptClass(QmlEngine *);
+ ~QmlContextScriptClass();
+
+ virtual QueryFlags queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id);
+ virtual QScriptValue property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id);
+ virtual void setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value);
+};
+
+class QmlObjectScriptClass : public QmlScriptClass
+{
+public:
+ QmlObjectScriptClass(QmlEngine *);
+ ~QmlObjectScriptClass();
+
+ virtual QueryFlags queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id);
+ virtual QScriptValue property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id);
+ virtual void setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value);
+};
+
+class QmlExpressionLog
+{
+public:
+ QmlExpressionLog();
+ QmlExpressionLog(const QmlExpressionLog &);
+ ~QmlExpressionLog();
+
+ QmlExpressionLog &operator=(const QmlExpressionLog &);
+
+ void setTime(quint32);
+ quint32 time() const;
+
+ QString expression() const;
+ void setExpression(const QString &);
+
+ QStringList warnings() const;
+ void addWarning(const QString &);
+
+ QVariant result() const;
+ void setResult(const QVariant &);
+
+private:
+ quint32 m_time;
+ QString m_expression;
+ QVariant m_result;
+ QStringList m_warnings;
+};
+
+class QmlExpressionPrivate
+{
+public:
+ QmlExpressionPrivate(QmlExpression *);
+ QmlExpressionPrivate(QmlExpression *, const QString &expr, bool);
+ QmlExpressionPrivate(QmlExpression *, void *expr, QmlRefCount *rc);
+ ~QmlExpressionPrivate();
+
+ QmlExpression *q;
+ QmlContext *ctxt;
+ QString expression;
+ QmlBasicScript sse;
+ void *sseData;
+ BindExpressionProxy *proxy;
+ QObject *me;
+ bool trackChange;
+
+ quint32 id;
+
+ void addLog(const QmlExpressionLog &);
+ QList<QmlExpressionLog> *log;
+};
+QT_END_NAMESPACE
+
+#endif // QMLENGINE_P_H
+
diff --git a/src/declarative/qml/qmlerror.cpp b/src/declarative/qml/qmlerror.cpp
new file mode 100644
index 0000000..149e173
--- /dev/null
+++ b/src/declarative/qml/qmlerror.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlerror.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlError
+ \brief The QmlError class encapsulates a QML error
+*/
+class QmlErrorPrivate
+{
+public:
+ QmlErrorPrivate();
+
+ QUrl url;
+ QString description;
+ int line;
+ int column;
+};
+
+QmlErrorPrivate::QmlErrorPrivate()
+: line(-1), column(-1)
+{
+}
+
+/*!
+ Create an empty error object.
+*/
+QmlError::QmlError()
+: d(new QmlErrorPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other.
+*/
+QmlError::QmlError(const QmlError &other)
+: d(new QmlErrorPrivate)
+{
+ *this = other;
+}
+
+/*!
+ Assign \a other to this error object.
+*/
+QmlError &QmlError::operator=(const QmlError &other)
+{
+ d->url = other.d->url;
+ d->description = other.d->description;
+ d->line = other.d->line;
+ d->column = other.d->column;
+ return *this;
+}
+
+/*!
+ \internal
+*/
+QmlError::~QmlError()
+{
+ delete d; d = 0;
+}
+
+/*!
+ Return the url for the file that caused this error.
+*/
+QUrl QmlError::url() const
+{
+ return d->url;
+}
+
+/*!
+ Set the \a url for the file that caused this error.
+*/
+void QmlError::setUrl(const QUrl &url)
+{
+ d->url = url;
+}
+
+/*!
+ Return the error description.
+*/
+QString QmlError::description() const
+{
+ return d->description;
+}
+
+/*!
+ Set the error \a description.
+*/
+void QmlError::setDescription(const QString &description)
+{
+ d->description = description;
+}
+
+/*!
+ Return the error line number.
+*/
+int QmlError::line() const
+{
+ return d->line;
+}
+
+/*!
+ Set the error \a line number.
+*/
+void QmlError::setLine(int line)
+{
+ d->line = line;
+}
+
+/*!
+ Return the error column number.
+*/
+int QmlError::column() const
+{
+ return d->column;
+}
+
+/*!
+ Set the error \a column number.
+*/
+void QmlError::setColumn(int column)
+{
+ d->column = column;
+}
+
+/*!
+ \relates QmlError
+ \fn QDebug operator<<(QDebug debug, const QmlError &error)
+
+ Output a human readable version of \a error to \a debug.
+*/
+
+QDebug operator<<(QDebug debug, const QmlError &error)
+{
+ QUrl url = error.url();
+
+ QString output;
+
+ output = url.toString() + QLatin1String(":") +
+ QString::number(error.line());
+
+ if(error.column() != -1)
+ output += QLatin1String(":") + QString::number(error.column());
+
+ output += QLatin1String(": ") + error.description();
+
+ debug << qPrintable(output);
+
+ if (error.line() > 0 && url.scheme() == QLatin1String("file")) {
+ QString file = url.toLocalFile();
+ QFile f(file);
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray data = f.readAll();
+ QTextStream stream(data, QIODevice::ReadOnly);
+ const QString code = stream.readAll();
+ const QStringList lines = code.split(QLatin1Char('\n'));
+
+ if (lines.count() >= error.line()) {
+ const QString &line = lines.at(error.line() - 1);
+ debug << "\n " << qPrintable(line);
+
+ if(error.column() > 0) {
+ int column = qMax(0, error.column() - 1);
+ column = qMin(column, line.length());
+
+ QByteArray ind;
+ ind.reserve(column);
+ for (int i = 0; i < column; ++i) {
+ const QChar ch = line.at(i);
+ if (ch.isSpace())
+ ind.append(ch.unicode());
+ else
+ ind.append(' ');
+ }
+ ind.append('^');
+ debug << "\n " << ind.constData();
+ }
+ }
+ }
+ }
+ return debug;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlerror.h b/src/declarative/qml/qmlerror.h
new file mode 100644
index 0000000..57d2f8f
--- /dev/null
+++ b/src/declarative/qml/qmlerror.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLERROR_H
+#define QMLERROR_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDebug;
+class QmlErrorPrivate;
+class Q_DECLARATIVE_EXPORT QmlError
+{
+public:
+ QmlError();
+ QmlError(const QmlError &);
+ QmlError &operator=(const QmlError &);
+ ~QmlError();
+
+ QUrl url() const;
+ void setUrl(const QUrl &);
+ QString description() const;
+ void setDescription(const QString &);
+ int line() const;
+ void setLine(int);
+ int column() const;
+ void setColumn(int);
+private:
+ QmlErrorPrivate *d;
+};
+
+QDebug Q_DECLARATIVE_EXPORT operator<<(QDebug debug, const QmlError &error);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLERROR_H
diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h
new file mode 100644
index 0000000..2c6b1ad
--- /dev/null
+++ b/src/declarative/qml/qmlexpression.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLEXPRESSION_H
+#define QMLEXPRESSION_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QmlRefCount;
+class QmlEngine;
+class QmlContext;
+class QmlExpressionPrivate;
+class QmlBasicScript;
+class Q_DECLARATIVE_EXPORT QmlExpression
+{
+public:
+ QmlExpression();
+ QmlExpression(QmlContext *, const QString &, QObject *);
+ QmlExpression(QmlContext *, const QString &, QObject *, bool);
+ QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me);
+ virtual ~QmlExpression();
+
+ QmlEngine *engine() const;
+ QmlContext *context() const;
+
+ QString expression() const;
+ void clearExpression();
+ virtual void setExpression(const QString &);
+ QVariant value();
+ bool isConstant() const;
+
+ bool trackChange() const;
+ void setTrackChange(bool);
+
+ QObject *scopeObject() const;
+
+ quint32 id() const;
+protected:
+ virtual void valueChanged();
+
+private:
+ friend class BindExpressionProxy;
+ friend class QmlDebugger;
+ friend class QmlContext;
+ QmlExpressionPrivate *d;
+};
+
+// LK: can't we merge with QmlExpression????
+class Q_DECLARATIVE_EXPORT QmlExpressionObject : public QObject,
+ public QmlExpression
+{
+ Q_OBJECT
+public:
+ QmlExpressionObject(QObject *parent = 0);
+ QmlExpressionObject(QmlContext *, const QString &, QObject *scope, QObject *parent = 0);
+ QmlExpressionObject(QmlContext *, const QString &, QObject *scope, bool);
+ QmlExpressionObject(QmlContext *, void *, QmlRefCount *, QObject *);
+
+public Q_SLOTS:
+ QVariant value();
+
+Q_SIGNALS:
+ void valueChanged();
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLEXPRESSION_H
+
diff --git a/src/declarative/qml/qmlinfo.cpp b/src/declarative/qml/qmlinfo.cpp
new file mode 100644
index 0000000..65a4298
--- /dev/null
+++ b/src/declarative/qml/qmlinfo.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlinfo.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlInfo
+ \brief The QmlInfo class prints warnings messages that include the file and line number for QML types.
+
+ When QML types display warning messages, it improves tracibility
+ if they include the QML file and line number on which the
+ particular instance was instantiated.
+
+ QmlInfo statements work just like regular Qt qDebug() statements.
+ To include the file and line number, an object must be passed. If
+ the file and line number is not available for that instance
+ (either it was not instantiated by the QML engine or location
+ information is disabled), "unknown location" will be used instead.
+
+ For example,
+
+ \code
+ qmlInfo(this) << "component property is a write-once property";
+ \endcode
+
+ prints
+
+ \code
+ QML ComponentInstance (unknown location): component property is a write-once property
+ \endcode
+*/
+
+/*!
+ Construct a QmlInfo, using \a object for file and line number
+ information.
+*/
+QmlInfo::QmlInfo(QObject *object)
+: QDebug(QtWarningMsg)
+{
+ *this << "QML";
+ if (object)
+ *this << object->metaObject()->className();
+ *this << "(unknown location):";
+}
+
+/*!
+ The destructor does nothing special.
+*/
+QmlInfo::~QmlInfo()
+{
+}
+
+/*!
+ \relates QmlInfo
+ \fn QmlInfo qmlInfo(QObject *me)
+ Constructs an instance of QmlInfo from \a me and returns it.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlinfo.h b/src/declarative/qml/qmlinfo.h
new file mode 100644
index 0000000..da8144c
--- /dev/null
+++ b/src/declarative/qml/qmlinfo.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLINFO_H
+#define QMLINFO_H
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlInfo : public QDebug
+{
+public:
+ QmlInfo(QObject *);
+ ~QmlInfo();
+};
+
+Q_DECLARATIVE_EXPORT inline QmlInfo qmlInfo(QObject *me)
+{
+ return QmlInfo(me);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLINFO_H
diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp
new file mode 100644
index 0000000..0617913
--- /dev/null
+++ b/src/declarative/qml/qmlinstruction.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qmlinstruction_p.h"
+#include "private/qmlcompiledcomponent_p.h"
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+void QmlCompiledComponent::dump(QmlInstruction *instr, int idx)
+{
+ QByteArray lineNumber = QByteArray::number(instr->line);
+ if (instr->line == (unsigned short)-1)
+ lineNumber = "NA";
+ const char *line = lineNumber.constData();
+
+ switch(instr->type) {
+ case QmlInstruction::Init:
+ qWarning() << idx << "\t" << line << "\t" << "INIT\t\t\t" << instr->init.dataSize;
+ break;
+ case QmlInstruction::CreateObject:
+ qWarning() << idx << "\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className;
+ break;
+ case QmlInstruction::SetId:
+ qWarning() << idx << "\t" << line << "\t" << "SETID\t\t\t" << instr->setId.value << "\t" << instr->setId.save << "\t\t" << primitives.at(instr->setId.value);
+ break;
+ case QmlInstruction::SetDefault:
+ qWarning() << idx << "\t" << line << "\t" << "SET_DEFAULT";
+ break;
+ case QmlInstruction::CreateComponent:
+ qWarning() << idx << "\t" << line << "\t" << "CREATE_COMPONENT\t" << instr->createComponent.count;
+ break;
+ case QmlInstruction::StoreMetaObject:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_META\t\t" << instr->storeMeta.data << "\t" << instr->storeMeta.slotData;
+ break;
+ case QmlInstruction::StoreReal:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_REAL\t\t" << instr->storeReal.propertyIndex << "\t" << instr->storeReal.value;
+ break;
+ case QmlInstruction::StoreInteger:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value;
+ break;
+ case QmlInstruction::StoreBool:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value;
+ break;
+ case QmlInstruction::StoreString:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_STRING\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
+ break;
+ case QmlInstruction::StoreColor:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_COLOR\t\t" << instr->storeColor.propertyIndex << "\t" << QString::number(instr->storeColor.value, 16);
+ break;
+ case QmlInstruction::StoreDate:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_DATE\t\t" << instr->storeDate.propertyIndex << "\t" << instr->storeDate.value;
+ break;
+ case QmlInstruction::StoreTime:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_TIME\t\t" << instr->storeTime.propertyIndex << "\t" << instr->storeTime.valueIndex;
+ break;
+ case QmlInstruction::StoreDateTime:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_DATETIME\t\t" << instr->storeDateTime.propertyIndex << "\t" << instr->storeDateTime.valueIndex;
+ break;
+ case QmlInstruction::StorePoint:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_POINT\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StorePointF:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_POINTF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreSize:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_SIZE\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreSizeF:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_SIZEF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreRect:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_RECT\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex;
+ break;
+ case QmlInstruction::StoreRectF:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_RECTF\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex;
+ break;
+ case QmlInstruction::StoreVariant:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
+ break;
+ case QmlInstruction::StoreObject:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex << "\t" << instr->storeObject.cast;
+ break;
+ case QmlInstruction::AssignCustomType:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_CUSTOMTYPE\t\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex;
+ break;
+ case QmlInstruction::StoreSignal:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value << "\t\t" << primitives.at(instr->storeSignal.value);
+ break;
+ case QmlInstruction::AssignConstant:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_CONSTANT\t" << instr->assignConstant.property << "\t" << instr->assignConstant.constant << "\t\t" << datas.at(instr->assignConstant.property) << primitives.at(instr->assignConstant.constant);
+ break;
+ case QmlInstruction::AssignSignal:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_SIGNAL\t\t" << instr->assignSignal.signal << "\t" << instr->assignSignal.value << "\t\t" << datas.at(instr->assignSignal.signal) << primitives.at(instr->assignSignal.value);
+ break;
+ case QmlInstruction::AssignSignalObject:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal << "\t\t\t" << datas.at(instr->assignSignalObject.signal);
+ break;
+ case QmlInstruction::AssignBinding:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_BINDING\t\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context << datas.at(instr->assignBinding.property) << primitives.at(instr->assignBinding.value);
+ break;
+ case QmlInstruction::AssignCompiledBinding:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context << datas.at(instr->assignBinding.property);
+ break;
+ case QmlInstruction::AssignValueSource:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t\t\t" << datas.at(instr->assignValueSource.property);
+ break;
+ case QmlInstruction::StoreBinding:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_BINDING\t\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context << primitives.at(instr->assignBinding.value);
+ break;
+ case QmlInstruction::StoreCompiledBinding:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context;
+ break;
+ case QmlInstruction::StoreValueSource:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property;
+ break;
+ case QmlInstruction::TryBeginObject:
+ qWarning() << idx << "\t" << line << "\t" << "TRY_BEGIN";
+ break;
+ case QmlInstruction::BeginObject:
+ qWarning() << idx << "\t" << line << "\t" << "BEGIN\t\t\t" << instr->begin.castValue;
+ break;
+ case QmlInstruction::TryCompleteObject:
+ qWarning() << idx << "\t" << line << "\t" << "TRY_COMPLETE";
+ break;
+ case QmlInstruction::CompleteObject:
+ qWarning() << idx << "\t" << line << "\t" << "COMPLETE\t\t" << instr->complete.castValue;
+ break;
+ case QmlInstruction::AssignObject:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_OBJECT\t\t" << instr->assignObject.property << "\t" << instr->assignObject.castValue << "\t\t" << ((instr->assignObject.property == -1)?QByteArray("default"):datas.at(instr->assignObject.property));
+ break;
+ case QmlInstruction::AssignObjectList:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_OBJECT_LIST\t" << instr->assignObject.property << "\t" << instr->assignObject.castValue << "\t\t" << ((instr->assignObject.property == -1)?QByteArray("default"):datas.at(instr->assignObject.property));
+ break;
+ case QmlInstruction::FetchAttached:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.id;
+ break;
+ case QmlInstruction::FetchQmlList:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_QMLLIST\t\t" << instr->fetchQmlList.property << "\t" << instr->fetchQmlList.type;
+ break;
+ case QmlInstruction::FetchQList:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_QLIST\t\t" << instr->fetch.property;
+ break;
+ case QmlInstruction::FetchObject:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH\t\t\t" << instr->fetch.property;
+ break;
+ case QmlInstruction::ResolveFetchObject:
+ qWarning() << idx << "\t" << line << "\t" << "RESOLVE_FETCH\t\t" << instr->fetch.property << "\t\t\t" << datas.at(instr->fetch.property);
+ break;
+ case QmlInstruction::PopFetchedObject:
+ qWarning() << idx << "\t" << line << "\t" << "POP";
+ break;
+ case QmlInstruction::PopQList:
+ qWarning() << idx << "\t" << line << "\t" << "POP_QLIST";
+ break;
+ case QmlInstruction::NoOp:
+ qWarning() << idx << "\t" << line << "\t" << "NOOP";
+ break;
+ case QmlInstruction::PushProperty:
+ qWarning() << idx << "\t" << line << "\t" << "PUSH_PROPERTY" << "\t\t" << instr->pushProperty.property;
+ break;
+ case QmlInstruction::AssignStackObject:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_STACK_OBJ" << "\t" << instr->assignStackObject.property << "\t" << instr->assignStackObject.object;
+ break;
+ case QmlInstruction::StoreStackObject:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_STACK_OBJ" << "\t" << instr->assignStackObject.property << "\t" << instr->assignStackObject.object;
+ break;
+ default:
+ qWarning() << idx << "\t" << line << "\t" << "XXX UNKOWN INSTRUCTION";
+ break;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
new file mode 100644
index 0000000..f465e9f
--- /dev/null
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLINSTRUCTION_P_H
+#define QMLINSTRUCTION_P_H
+
+#include <qfxglobal.h>
+
+
+QT_BEGIN_NAMESPACE
+class QmlCompiledComponent;
+class Q_DECLARATIVE_EXPORT QmlInstruction
+{
+public:
+ enum Type {
+ //
+ // Object Creation
+ //
+ // CreateObject - Create a new object instance and push it on the
+ // object stack
+ // SetId - Set the id of the object on the top of the object stack
+ // SetDefault - Sets the instance on the top of the object stack to
+ // be the context's default object.
+ // StoreMetaObject - Assign the dynamic metaobject to object on the
+ // top of the stack.
+ Init, /* init */
+ CreateObject, /* create */
+ SetId, /* setId */
+ SetDefault,
+ CreateComponent, /* createComponent */
+ StoreMetaObject, /* storeMeta */
+
+ //
+ // Precomputed single assignment
+ //
+ // StoreReal - Store a qreal in a core property
+ // StoreInteger - Store a int or uint in a core property
+ // StoreBool - Store a bool in a core property
+ // StoreString - Store a QString in a core property
+ // StoreColor - Store a QColor in a core property
+ // StoreDate - Store a QDate in a core property
+ // StoreTime - Store a QTime in a core property
+ // StoreDateTime - Store a QDateTime in a core property
+ // StoreVariant - Store a QVariant in a core property
+ // StoreObject - Pop the object on the top of the object stack and
+ // store it in a core property
+ StoreReal, /* storeReal */
+ StoreInstructionsStart = StoreReal,
+ StoreInteger, /* storeInteger */
+ StoreBool, /* storeBool */
+ StoreString, /* storeString */
+ StoreColor, /* storeColor */
+ StoreDate, /* storeDate */
+ StoreTime, /* storeTime */
+ StoreDateTime, /* storeDateTime */
+ StorePoint, /* storeRealPair */
+ StorePointF, /* storeRealPair */
+ StoreSize, /* storeRealPair */
+ StoreSizeF, /* storeRealPair */
+ StoreRect, /* storeRect */
+ StoreRectF, /* storeRect */
+ StoreVariant, /* storeString */
+ StoreObject, /* storeObject */
+ StoreInstructionsEnd = StoreObject,
+
+ StoreSignal, /* storeSignal */
+
+ StoreObjectQmlList,
+
+ // XXX need to handle storing objects in variants
+
+ //
+ // Unresolved single assignment
+ //
+ // AssignConstant - Store a value in a property. Will resolve into
+ // a Store* instruction.
+ // AssignSignal - Set a signal handler on the property. Will resolve
+ // into a Store*Signal instruction.
+ AssignConstant, /* assignConstant */
+ AssignSignal, /* assignSignal */
+ AssignSignalObject, /* assignSignalObject */
+ AssignCustomType, /* assignCustomType */
+
+ AssignBinding, /* assignBinding */
+ AssignCompiledBinding, /* assignBinding */
+ AssignValueSource, /* assignValueSource */
+ StoreBinding, /* assignBinding */
+ StoreCompiledBinding, /* assignBinding */
+ StoreValueSource, /* assignValueSource */
+
+ TryBeginObject,
+ BeginObject, /* begin */
+ TryCompleteObject,
+ CompleteObject, /* complete */
+
+ AssignObject, /* assignObject */
+ AssignObjectList, /* assignObject */
+
+ FetchAttached, /* fetchAttached */
+ FetchQmlList, /* fetchQmlList */
+ FetchQList, /* fetch */
+ FetchObject, /* fetch */
+ ResolveFetchObject, /* fetch */
+
+ //
+ // Stack manipulation
+ //
+ // PopFetchedObject - Remove an object from the object stack
+ // PopQList - Remove a list from the list stack
+ PopFetchedObject,
+ PopQList,
+
+ //
+ // Expression optimizations
+ //
+ // PushProperty - Save the property for later use
+ // AssignStackObject - Assign the stack object
+ // StoreStackObject - Assign the stack object (no checks)
+ PushProperty, /* pushProperty */
+ AssignStackObject, /* assignStackObject */
+ StoreStackObject, /* assignStackObject */
+
+
+ //
+ // Miscellaneous
+ //
+ // NoOp - Do nothing
+ NoOp
+ };
+ QmlInstruction()
+ : type(NoOp), line(0) {}
+
+ Type type;
+ unsigned short line;
+ union {
+ struct {
+ int dataSize;
+ int bindingsSize;
+ int parserStatusSize;
+ } init;
+ struct {
+ int type;
+ int data;
+ } create;
+ struct {
+ int data;
+ int slotData;
+ } storeMeta;
+ struct {
+ int value;
+ int save;
+ } setId;
+ struct {
+ int property;
+ int constant;
+ } assignConstant;
+ struct {
+ int property;
+ int castValue;
+ } assignObject;
+ struct {
+ int property;
+ } assignValueSource;
+ struct {
+ int property;
+ int value;
+ short context;
+ short category;
+ } assignBinding;
+ struct {
+ int property;
+ bool isObject;
+ } fetch;
+ struct {
+ int property;
+ int type;
+ } fetchQmlList;
+ struct {
+ int castValue;
+ } complete;
+ struct {
+ int castValue;
+ } begin;
+ struct {
+ int propertyIndex;
+ float value;
+ } storeReal;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeInteger;
+ struct {
+ int propertyIndex;
+ bool value;
+ } storeBool;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeString;
+ struct {
+ int propertyIndex;
+ unsigned int value;
+ } storeColor;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeDate;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeTime;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeDateTime;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeRealPair;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeRect;
+ struct {
+ int propertyIndex;
+ int cast;
+ } storeObject;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } assignCustomType;
+ struct {
+ int signalIndex;
+ int value;
+ } storeSignal;
+ struct {
+ int signal;
+ int value;
+ } assignSignal;
+ struct {
+ int signal;
+ } assignSignalObject;
+ struct {
+ int count;
+ int endLine;
+ int metaObject;
+ } createComponent;
+ struct {
+ int id;
+ } fetchAttached;
+ struct {
+ int property;
+ } pushProperty;
+ struct {
+ int property;
+ int object;
+ } assignStackObject;
+ };
+
+ void dump(QmlCompiledComponent *);
+};
+
+#endif // QMLINSTRUCTION_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmllist.h b/src/declarative/qml/qmllist.h
new file mode 100644
index 0000000..cc13924
--- /dev/null
+++ b/src/declarative/qml/qmllist.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLLIST_H
+#define QMLLIST_H
+
+#include <QtDeclarative/qmlprivate.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+template<typename T>
+class QmlList : private QmlPrivate::ListInterface
+{
+public:
+ virtual void append(T) = 0;
+ virtual void insert(int, T) = 0;
+ virtual void removeAt(int) = 0;
+ virtual T at(int) const = 0;
+ virtual int count() const = 0;
+ virtual void clear() = 0;
+ QmlList<T> &operator<<(T t) { append(t); return *this; }
+
+protected:
+ virtual int type() const { return qMetaTypeId<T>(); }
+ virtual void append(void *d) { const T &v = *(T *)d; append(v); }
+ virtual void insert(int i, void *d) { const T &v = *(T *)d; insert(i, v); }
+ virtual void at(int i, void *p) const { const T &v = at(i); *((T*)p) = v; }
+};
+
+template<typename T>
+class QmlConcreteList : public QList<T>, public QmlList<T>
+{
+public:
+ virtual void append(T v) { QList<T>::append(v); }
+ virtual void insert(int i, T v) { QList<T>::insert(i, v); }
+ virtual void clear() { QList<T>::clear(); }
+ virtual T at(int i) const { return QList<T>::at(i); }
+ virtual void removeAt(int i) { QList<T>::removeAt(i); }
+ virtual int count() const { return QList<T>::count(); }
+};
+
+#define QML_DECLARE_LIST_PROXY(ClassName, ListType, ListName) \
+class Qml_ProxyList_ ##ListName : public QmlList<ListType> \
+{ \
+ public: \
+ virtual void removeAt(int idx) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _removeAt(idx); \
+ } \
+ virtual int count() const \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ return p->ListName ## _count(); \
+ } \
+ virtual void append(ListType v) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _append(v); \
+ } \
+ virtual void insert(int idx, ListType v) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _insert(idx, v); \
+ } \
+ virtual ListType at(int idx) const \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ return p->ListName ## _at(idx); \
+ } \
+ virtual void clear() \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _clear(); \
+ } \
+}; \
+friend class Qml_ProxyList_ ##ListName ; \
+Qml_ProxyList_##ListName ListName;
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLLIST_H
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
new file mode 100644
index 0000000..59d6b38
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -0,0 +1,1119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlmetaproperty.h"
+#include "qmlmetaproperty_p.h"
+#include <qml.h>
+#include <qfxperf.h>
+#include <QStringList>
+#include <qmlbindablevalue.h>
+#include <qmlcontext.h>
+#include "qmlboundsignal_p.h"
+#include <math.h>
+#include <QtCore/qdebug.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QMetaPropertyEx : public QMetaProperty
+{
+public:
+ QMetaPropertyEx()
+ : propertyType(-1) {}
+
+ QMetaPropertyEx(const QMetaProperty &p)
+ : QMetaProperty(p), propertyType(p.userType()) {}
+
+ QMetaPropertyEx(const QMetaPropertyEx &o)
+ : QMetaProperty(o),
+ propertyType(o.propertyType) {}
+
+ QMetaPropertyEx &operator=(const QMetaPropertyEx &o)
+ {
+ static_cast<QMetaProperty *>(this)->operator=(o);
+ propertyType = o.propertyType;
+ return *this;
+ }
+
+ private:
+ friend class QmlMetaProperty;
+ int propertyType;
+};
+
+
+/*!
+ \class QmlMetaProperty
+ \brief The QmlMetaProperty class abstracts accessing QML properties.
+ */
+
+/*!
+ Create an invalid QmlMetaProperty.
+*/
+QmlMetaProperty::QmlMetaProperty()
+: d(new QmlMetaPropertyPrivate)
+{
+}
+
+/*!
+ The destructor deletes its heap data.
+ */
+QmlMetaProperty::~QmlMetaProperty()
+{
+ delete d; d = 0;
+}
+
+// ### not thread safe
+static QHash<const QMetaObject *, QMetaPropertyEx> qmlCacheDefProp;
+
+
+/*!
+ Creates a QmlMetaProperty for the default property of \a obj. If there is no
+ default property, an invalid QmlMetaProperty will be created.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj)
+{
+ initDefault(obj);
+}
+
+/*!
+ \internal
+ Creates a QmlMetaProperty for the default property of \a obj. If there is no
+ default property, an invalid QmlMetaProperty will be created.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->context = ctxt;
+ initDefault(obj);
+}
+
+void QmlMetaProperty::initDefault(QObject *obj)
+{
+ if (!obj)
+ return;
+
+ d->object = obj;
+ QHash<const QMetaObject *, QMetaPropertyEx>::ConstIterator iter =
+ qmlCacheDefProp.find(obj->metaObject());
+ if (iter != qmlCacheDefProp.end()) {
+ d->prop = *iter;
+ d->propType = iter->propertyType;
+ d->coreIdx = iter->propertyType;
+ } else {
+ QMetaPropertyEx p(QmlMetaType::defaultProperty(obj));
+ d->prop = p;
+ d->propType = p.propertyType;
+ d->coreIdx = d->prop.propertyIndex();
+ if (!QObjectPrivate::get(obj)->metaObject)
+ qmlCacheDefProp.insert(obj->metaObject(), d->prop);
+ }
+ if (d->prop.name() != 0) {
+ d->type = Property | Default;
+ d->name = QLatin1String(d->prop.name());
+ }
+}
+
+/*!
+ \internal
+
+ Creates a QmlMetaProperty for the property at index \a idx of \a obj.
+
+ The QmlMetaProperty is assigned category \a cat.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, int idx, PropertyCategory cat, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->context = ctxt;
+ d->object = obj;
+ d->type = Property;
+ d->category = cat;
+ QMetaPropertyEx p(obj->metaObject()->property(idx));
+ d->prop = p;
+ d->propType = p.propertyType;
+ d->coreIdx = idx;
+ if (d->prop.name() != 0)
+ d->name = QLatin1String(d->prop.name());
+}
+
+// ### Not thread safe!!!!
+static QHash<const QMetaObject *, QHash<QString, QMetaPropertyEx> > qmlCacheProps;
+/*!
+ Creates a QmlMetaProperty for the property \a name of \a obj.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name)
+: d(new QmlMetaPropertyPrivate)
+{
+ initProperty(obj, name);
+}
+
+/*!
+ \internal
+ Creates a QmlMetaProperty for the property \a name of \a obj.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::MetaProperty> perf;
+#endif
+
+ d->context = ctxt;
+ initProperty(obj, name);
+}
+
+void QmlMetaProperty::initProperty(QObject *obj, const QString &name)
+{
+ d->name = name;
+ d->object = obj;
+ if (name.isEmpty() || !obj)
+ return;
+
+ if (name.at(0).isUpper()) {
+ // Attached property
+ d->attachedFunc = QmlMetaType::attachedPropertiesFuncId(name.toLatin1());
+ if (d->attachedFunc != -1)
+ d->type = Property | Attached;
+ return;
+ } else if (name.count() >= 3 && name.startsWith(QLatin1String("on")) && name.at(2).isUpper()) {
+ // Signal
+ QString signalName = name.mid(2);
+ signalName[0] = signalName.at(0).toLower();
+
+ d->findSignalInt(obj, signalName);
+ if (d->signal.signature() != 0) {
+ d->type = SignalProperty;
+ return;
+ }
+ }
+
+ // Property
+ QHash<QString, QMetaPropertyEx> &props = qmlCacheProps[obj->metaObject()];
+ QHash<QString, QMetaPropertyEx>::ConstIterator iter = props.find(name);
+ if (iter != props.end()) {
+ d->prop = *iter;
+ d->propType = iter->propertyType;
+ d->coreIdx = iter->propertyIndex();
+ } else {
+ QMetaPropertyEx p = QmlMetaType::property(obj, name.toLatin1().constData());
+ d->prop = p;
+ d->propType = p.propertyType;
+ d->coreIdx = p.propertyIndex();
+ if (!QObjectPrivate::get(obj)->metaObject)
+ props.insert(name, p);
+ }
+ if (d->prop.name() != 0)
+ d->type = Property;
+
+ if (d->type == Invalid) {
+ int sig = findSignal(obj, name.toLatin1());
+ if (sig != -1) {
+ d->signal = obj->metaObject()->method(sig);
+ d->type = Signal;
+ d->coreIdx = sig;
+ }
+ }
+}
+
+/*!
+ Create a copy of \a other.
+*/
+QmlMetaProperty::QmlMetaProperty(const QmlMetaProperty &other)
+: d(new QmlMetaPropertyPrivate(*other.d))
+{
+}
+
+/*!
+ \enum QmlMetaProperty::PropertyCategory
+
+ This enum specifies a category of QML property.
+
+ \value Unknown The category is unknown. This will never be returned from propertyCategory()
+ \value InvalidProperty The property is invalid.
+ \value Bindable The property is a QmlBindableValue.
+ \value List The property is a QList pointer
+ \value QmlList The property is a QmlList pointer
+ \value Object The property is a QObject derived type pointer
+ \value Normal The property is none of the above.
+ */
+
+/*!
+ \enum QmlMetaProperty::Type
+
+ This enum specifies a type of QML property.
+
+ \value Invalid The property is invalid.
+ \value Property The property is a regular Qt property.
+ \value SignalProperty The property is a signal property.
+ \value Signal The property is a signal.
+ \value Default The property is the default property.
+ \value Attached The property is an attached property.
+*/
+
+/*!
+ Returns the property category.
+*/
+QmlMetaProperty::PropertyCategory QmlMetaProperty::propertyCategory() const
+{
+ return d->propertyCategory();
+}
+
+QmlMetaProperty::PropertyCategory
+QmlMetaPropertyPrivate::propertyCategory() const
+{
+ if (category == QmlMetaProperty::Unknown) {
+ int type = propertyType();
+ if (type == QmlMetaProperty::Invalid)
+ category = QmlMetaProperty::InvalidProperty;
+ else if (type == qMetaTypeId<QmlBindableValue *>())
+ category = QmlMetaProperty::Bindable;
+ else if (QmlMetaType::isList(type))
+ category = QmlMetaProperty::List;
+ else if (QmlMetaType::isQmlList(type))
+ category = QmlMetaProperty::QmlList;
+ else if (QmlMetaType::isObject(type))
+ category = QmlMetaProperty::Object;
+ else
+ category = QmlMetaProperty::Normal;
+ }
+ return category;
+}
+
+/*!
+ Returns the property category of \a prop.
+*/
+QmlMetaProperty::PropertyCategory
+QmlMetaProperty::propertyCategory(const QMetaProperty &prop)
+{
+ if (prop.name()) {
+ int type = 0;
+ if (prop.type() == QVariant::LastType)
+ type = qMetaTypeId<QVariant>();
+ else if (prop.type() == QVariant::UserType)
+ type = prop.userType();
+ else
+ type = prop.type();
+
+ if (type == qMetaTypeId<QmlBindableValue *>())
+ return Bindable;
+ else if (QmlMetaType::isList(type))
+ return List;
+ else if (QmlMetaType::isQmlList(type))
+ return QmlList;
+ else if (QmlMetaType::isObject(type))
+ return Object;
+ else
+ return Normal;
+ } else {
+ return InvalidProperty;
+ }
+}
+
+/*!
+ Returns the type name of the property, or 0 if the property has no type
+ name.
+*/
+const char *QmlMetaProperty::propertyTypeName() const
+{
+ if (d->prop.name()) {
+ return d->prop.typeName();
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ Returns true if \a other and this QmlMetaProperty represent the same
+ property.
+*/
+bool QmlMetaProperty::operator==(const QmlMetaProperty &other) const
+{
+ return d->prop.name() == other.d->prop.name() &&
+ d->signal.signature() == other.d->signal.signature() &&
+ d->type == other.d->type &&
+ d->object == other.d->object;
+}
+
+/*!
+ Returns the QVariant type of the property, or QVariant::Invalid if the
+ property has no QVariant type.
+*/
+int QmlMetaProperty::propertyType() const
+{
+ return d->propertyType();
+}
+
+int QmlMetaPropertyPrivate::propertyType() const
+{
+ int rv = QVariant::Invalid;
+
+ if (prop.name()) {
+ if (propType == (int)QVariant::LastType)
+ rv = qMetaTypeId<QVariant>();
+ else
+ rv = propType;
+ } else if (attachedFunc) {
+ rv = qMetaTypeId<QObject *>();
+ }
+
+ return rv;
+}
+
+/*!
+ Returns the type of the property.
+*/
+QmlMetaProperty::Type QmlMetaProperty::type() const
+{
+ return (Type)d->type;
+}
+
+/*!
+ Returns true if this QmlMetaProperty represents a regular Qt property.
+*/
+bool QmlMetaProperty::isProperty() const
+{
+ return type() & Property;
+}
+
+/*!
+ Returns true if this QmlMetaProperty represents a default property.
+*/
+bool QmlMetaProperty::isDefault() const
+{
+ return type() & Default;
+}
+
+/*!
+ Returns the QmlMetaProperty's QObject.
+*/
+QObject *QmlMetaProperty::object() const
+{
+ return d->object;
+}
+
+/*!
+ Assign \a other to this QmlMetaProperty.
+*/
+QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other)
+{
+ d->name = other.d->name;
+ d->prop = other.d->prop;
+ d->propType = other.d->propType;
+ d->type = other.d->type;
+ d->signal = other.d->signal;
+ d->coreIdx = other.d->coreIdx;
+ d->attachedFunc = other.d->attachedFunc;
+ d->object = other.d->object;
+ d->category = other.d->category;
+ return *this;
+}
+
+/*!
+ Returns true if the property is writable, otherwise false.
+*/
+bool QmlMetaProperty::isWritable() const
+{
+ if (propertyCategory() == List || propertyCategory() == QmlList)
+ return true;
+ else if (d->prop.name() != 0)
+ return d->prop.isWritable();
+ else if (type() & SignalProperty)
+ return true;
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is designable, otherwise false.
+*/
+bool QmlMetaProperty::isDesignable() const
+{
+ if (d->prop.name() != 0)
+ return d->prop.isDesignable();
+ else
+ return false;
+}
+
+/*!
+ Returns true if the QmlMetaProperty refers to a valid property, otherwise
+ false.
+*/
+bool QmlMetaProperty::isValid() const
+{
+ return type() != Invalid;
+}
+
+/*!
+ Returns all of \a obj's Qt properties.
+*/
+QStringList QmlMetaProperty::properties(QObject *obj)
+{
+ if (!obj)
+ return QStringList();
+
+ QStringList rv;
+ const QMetaObject *mo = obj->metaObject();
+ for (int ii = 0; ii < mo->propertyCount(); ++ii) {
+ QMetaProperty prop = mo->property(ii);
+ rv << QLatin1String(prop.name());
+ }
+
+ return rv;
+}
+
+/*!
+ Return the name of this QML property.
+*/
+QString QmlMetaProperty::name() const
+{
+ return d->name;
+}
+
+/*!
+ Returns the \l{QMetaProperty} {Qt property} associated with
+ this QML property.
+ */
+const QMetaProperty &QmlMetaProperty::property() const
+{
+ return d->prop;
+}
+
+/*!
+ Returns the binding associated with this property, or 0 if no binding
+ exists.
+*/
+QmlBindableValue *QmlMetaProperty::binding()
+{
+ if (!isProperty() || type() & Attached)
+ return 0;
+
+ const QObjectList &children = object()->children();
+ for (QObjectList::ConstIterator iter = children.begin();
+ iter != children.end(); ++iter) {
+ QObject *child = *iter;
+ if (child->metaObject() == &QmlBindableValue::staticMetaObject) {
+ QmlBindableValue *v = static_cast<QmlBindableValue *>(child);
+ if (v->property() == *this)
+ return v;
+ }
+ }
+ return 0;
+}
+
+/*! \internal */
+int QmlMetaProperty::findSignal(const QObject *obj, const char *name)
+{
+ const QMetaObject *mo = obj->metaObject();
+ int methods = mo->methodCount();
+ for (int ii = 0; ii < methods; ++ii) {
+ QMetaMethod method = mo->method(ii);
+ if (method.methodType() != QMetaMethod::Signal)
+ continue;
+
+ QByteArray methodName = method.signature();
+ int idx = methodName.indexOf('(');
+ methodName = methodName.left(idx);
+
+ if (methodName == name)
+ return ii;
+ }
+ return -1;
+}
+
+void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name)
+{
+ const QMetaObject *mo = obj->metaObject();
+
+ int methods = mo->methodCount();
+ for (int ii = 0; ii < methods; ++ii) {
+ QMetaMethod method = mo->method(ii);
+ QString methodName = QLatin1String(method.signature());
+ int idx = methodName.indexOf(QLatin1Char('('));
+ methodName = methodName.left(idx);
+
+ if (methodName == name) {
+ signal = method;
+ coreIdx = ii;
+ return;
+ }
+ }
+}
+
+QObject *QmlMetaPropertyPrivate::attachedObject() const
+{
+ if (attachedFunc == -1)
+ return 0;
+ else
+ return qmlAttachedPropertiesObjectById(attachedFunc, object);
+}
+
+/*!
+ Returns the property value.
+*/
+QVariant QmlMetaProperty::read() const
+{
+ if (type() & SignalProperty) {
+
+ const QObjectList &children = object()->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QmlBoundSignal *sig = qobject_cast<QmlBoundSignal *>(children.at(ii));
+ if (sig && sig->index() == d->coreIdx)
+ return sig->expression();
+ }
+ } else if (type() & Property) {
+ if (type() & Attached)
+ return QVariant::fromValue(d->attachedObject());
+ else
+ return d->prop.read(object());
+ }
+ return QVariant();
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value)
+{
+ QString expr = value.toString();
+ const QObjectList &children = object->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QmlBoundSignal *sig = qobject_cast<QmlBoundSignal *>(children.at(ii));
+ if (sig && sig->index() == coreIdx) {
+ if (expr.isEmpty()) {
+ sig->disconnect();
+ sig->deleteLater();
+ } else {
+ sig->setExpression(expr);
+ }
+ return;
+ }
+ }
+
+ if (!expr.isEmpty()) {
+ // XXX scope
+ (void *)new QmlBoundSignal(QmlContext::activeContext(), expr, object,
+ coreIdx, object);
+ }
+}
+
+void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value)
+{
+ if (prop.isEnumType()) {
+ QVariant v = value;
+ if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles
+ double integral;
+ double fractional = modf(value.toDouble(), &integral);
+ if (qFuzzyCompare(fractional, (double)0.0))
+ v.convert(QVariant::Int);
+ }
+ prop.write(object, v);
+ } else {
+ if (!value.isValid())
+ return;
+
+ int t = propertyType();
+ int vt = value.type();
+
+ if (vt == t ||
+ value.userType() == t) {
+
+ void *a[1];
+ a[0] = (void *)value.constData();
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+
+ } else if (qMetaTypeId<QVariant>() == t) {
+
+ prop.write(object, value);
+
+ } else if (propertyCategory() == QmlMetaProperty::Object) {
+
+ QObject *o = QmlMetaType::toQObject(value);
+ if (o)
+ prop.write(object, QmlMetaType::fromObject(o, propertyType()));
+
+ } else if (propertyCategory() == QmlMetaProperty::List) {
+
+ int listType = QmlMetaType::listType(t);
+ if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ const QList<QObject *> &list =
+ qvariant_cast<QList<QObject *> >(value);
+ QVariant listVar = prop.read(object);
+ QmlMetaType::clear(listVar);
+ for (int ii = 0; ii < list.count(); ++ii) {
+ QVariant v = QmlMetaType::fromObject(list.at(ii), listType);
+ QmlMetaType::append(listVar, v);
+ }
+
+ } else if (vt == listType ||
+ value.userType() == listType) {
+ QVariant listVar = prop.read(object);
+ if (!QmlMetaType::append(listVar, value)) {
+ qWarning() << "QmlMetaProperty: Unable to assign object to list";
+ }
+ }
+ } else if (propertyCategory() == QmlMetaProperty::QmlList) {
+ // XXX - optimize!
+ QVariant list = prop.read(object);
+ QmlPrivate::ListInterface *li =
+ *(QmlPrivate::ListInterface **)list.constData();
+
+ int type = li->type();
+
+ if (QObject *obj = QmlMetaType::toQObject(value)) {
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *objMo = obj->metaObject();
+ bool found = false;
+ while(!found && objMo) {
+ if (objMo == mo)
+ found = true;
+ else
+ objMo = objMo->superClass();
+ }
+
+ if (!found) {
+ qWarning() << "Unable to assign object to list";
+ return;
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ void *d = (void *)&obj;
+ li->append(d);
+ }
+ } else if (propertyCategory() == QmlMetaProperty::Normal) {
+
+ switch(t) {
+ case QVariant::Double:
+ {
+ qreal r;
+ bool found = true;
+ if (vt == QVariant::Int) {
+ r = value.toInt();
+ } else if (vt == QVariant::UInt) {
+ r = value.toUInt();
+ } else {
+ found = false;
+ }
+
+ if (found) {
+ void *a[1];
+ a[0] = &r;
+ QMetaObject::metacall(object,
+ QMetaObject::WriteProperty,
+ coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+ case QVariant::Int:
+ {
+ int i;
+ bool found = true;
+ if (vt == QVariant::Double) {
+ i = (int)value.toDouble();
+ } else if (vt == QVariant::UInt) {
+ i = (int)value.toUInt();
+ } else {
+ found = false;
+ }
+
+ if (found) {
+ void *a[1];
+ a[0] = &i;
+ QMetaObject::metacall(object,
+ QMetaObject::WriteProperty,
+ coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+ case QVariant::String:
+ {
+ QString s;
+ bool found = true;
+ if (vt == QVariant::ByteArray) {
+ s = QLatin1String(value.toByteArray());
+ } else {
+ found = false;
+ }
+
+ if (found) {
+ void *a[1];
+ a[0] = &s;
+ QMetaObject::metacall(object,
+ QMetaObject::WriteProperty,
+ coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+
+ default:
+ break;
+ }
+ prop.write(object, value);
+ }
+
+ }
+}
+
+/*!
+ Set the property value to \a value.
+*/
+void QmlMetaProperty::write(const QVariant &value) const
+{
+ if (type() & SignalProperty) {
+
+ d->writeSignalProperty(value);
+
+ } else if (d->prop.name()) {
+
+ if (d->prop.isEnumType()) {
+ QVariant v = value;
+ if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles
+ double integral;
+ double fractional = modf(value.toDouble(), &integral);
+ if (qFuzzyCompare(fractional, (double)0.0))
+ v.convert(QVariant::Int);
+ }
+ d->prop.write(object(), v);
+ } else {
+ if (!value.isValid())
+ return;
+
+ int t = propertyType();
+ int vt = value.type();
+
+ if (vt == t ||
+ value.userType() == t) {
+
+ void *a[1];
+ a[0] = (void *)value.constData();
+ QMetaObject::metacall(object(), QMetaObject::WriteProperty, d->coreIdx, a);
+
+ } else if (qMetaTypeId<QVariant>() == t) {
+
+ d->prop.write(object(), value);
+
+ } else if (propertyCategory() == Object) {
+
+ QObject *o = QmlMetaType::toQObject(value);
+ if (o)
+ d->prop.write(object(), QmlMetaType::fromObject(o, propertyType()));
+
+ } else if (propertyCategory() == List) {
+
+ int listType = QmlMetaType::listType(t);
+ if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ const QList<QObject *> &list =
+ qvariant_cast<QList<QObject *> >(value);
+ QVariant listVar = d->prop.read(object());
+ QmlMetaType::clear(listVar);
+ for (int ii = 0; ii < list.count(); ++ii) {
+ QVariant v = QmlMetaType::fromObject(list.at(ii), listType);
+ QmlMetaType::append(listVar, v);
+ }
+
+ } else if (vt == listType ||
+ value.userType() == listType) {
+ QVariant listVar = d->prop.read(object());
+ if (!QmlMetaType::append(listVar, value)) {
+ qWarning() << "QmlMetaProperty: Unable to assign object to list";
+ }
+ }
+ } else if (propertyCategory() == QmlList) {
+ // XXX - optimize!
+ QVariant list = d->prop.read(object());
+ QmlPrivate::ListInterface *li =
+ *(QmlPrivate::ListInterface **)list.constData();
+
+ int type = li->type();
+
+ if (QObject *obj = QmlMetaType::toQObject(value)) {
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *objMo = obj->metaObject();
+ bool found = false;
+ while(!found && objMo) {
+ if (objMo == mo)
+ found = true;
+ else
+ objMo = objMo->superClass();
+ }
+
+ if (!found) {
+ qWarning() << "Unable to assign object to list";
+ return;
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ void *d = (void *)&obj;
+ li->append(d);
+ }
+ } else if (propertyCategory() == Normal) {
+
+ switch(t) {
+ case QVariant::Double:
+ {
+ qreal r;
+ bool found = true;
+ if (vt == QVariant::Int) {
+ r = value.toInt();
+ } else if (vt == QVariant::UInt) {
+ r = value.toUInt();
+ } else {
+ found = false;
+ }
+
+ if (found) {
+ void *a[1];
+ a[0] = &r;
+ QMetaObject::metacall(object(),
+ QMetaObject::WriteProperty,
+ d->coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+ case QVariant::Int:
+ {
+ int i;
+ bool found = true;
+ if (vt == QVariant::Double) {
+ i = (int)value.toDouble();
+ } else if (vt == QVariant::UInt) {
+ i = (int)value.toUInt();
+ } else {
+ found = false;
+ }
+
+ if (found) {
+ void *a[1];
+ a[0] = &i;
+ QMetaObject::metacall(object(),
+ QMetaObject::WriteProperty,
+ d->coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+ case QVariant::String:
+ {
+ QString s;
+ bool found = true;
+ if (vt == QVariant::ByteArray) {
+ s = QLatin1String(value.toByteArray());
+ } else {
+ found = false;
+ }
+
+ if (found) {
+ void *a[1];
+ a[0] = &s;
+ QMetaObject::metacall(object(),
+ QMetaObject::WriteProperty,
+ d->coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+
+ default:
+ break;
+ }
+ d->prop.write(object(), value);
+ }
+
+ }
+ }
+}
+
+/*!
+ Returns true if the property has a change notifier signal, otherwise false.
+*/
+bool QmlMetaProperty::hasChangedNotifier() const
+{
+ if (type() & Property && !(type() & Attached)) {
+ return d->prop.hasNotifySignal();
+ }
+ return false;
+}
+
+/*!
+ Returns true if the property needs a change notifier signal for bindings
+ to remain upto date, false otherwise.
+
+ Some properties, such as attached properties or those whose value never
+ changes, do not require a change notifier.
+*/
+bool QmlMetaProperty::needsChangedNotifier() const
+{
+ return type() & Property && !(type() & Attached);
+}
+
+/*!
+ Connects the property's change notifier signal to the
+ specified \a method of the \a dest object and returns
+ true. Returns false if this metaproperty does not
+ represent a regular Qt property or if it has no
+ change notifier signal, or if the \a dest object does
+ not have the specified \a method.
+*/
+bool QmlMetaProperty::connectNotifier(QObject *dest, int method) const
+{
+ if (!(type() & Property) || type() & Attached)
+ return false;
+
+ if (d->prop.hasNotifySignal()) {
+ return QMetaObject::connect(d->object, d->prop.notifySignalIndex(), dest, method, Qt::DirectConnection);
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Connects the property's change notifier signal to the
+ specified \a slot of the \a dest object and returns
+ true. Returns false if this metaproperty does not
+ represent a regular Qt property or if it has no
+ change notifier signal, or if the \a dest object does
+ not have the specified \a slot.
+*/
+bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const
+{
+ if (!(type() & Property) || type() & Attached)
+ return false;
+
+ if (d->prop.hasNotifySignal()) {
+ QByteArray signal(QByteArray("2") + d->prop.notifySignal().signature());
+ return QObject::connect(d->object, signal.constData(), dest, slot);
+ } else {
+ return false;
+ }
+}
+
+/*! \internal */
+void QmlMetaProperty::emitSignal()
+{
+ if (type() & Signal) {
+ if (d->signal.parameterTypes().isEmpty())
+ d->object->metaObject()->activate(d->object, d->coreIdx, 0);
+ else
+ qWarning() << "QmlMetaProperty: Cannot emit signal with parameters";
+ }
+}
+
+/*!
+ Return the Qt metaobject index of the property.
+*/
+int QmlMetaProperty::coreIndex() const
+{
+ return d->coreIdx;
+}
+
+/*!
+ Returns the property information serialized into a single integer.
+ QmlMetaProperty uses the bottom 24 bits only.
+*/
+quint32 QmlMetaProperty::save() const
+{
+ quint32 rv = 0;
+ if (type() & Attached) {
+ rv = d->attachedFunc;
+ } else if (type() != Invalid) {
+ rv = d->coreIdx;
+ }
+
+ Q_ASSERT(rv <= 0xFFFF);
+ Q_ASSERT(type() <= 0xFF);
+ rv |= (type() << 16);
+
+ return rv;
+}
+
+/*!
+ Restore a QmlMetaProperty from a previously saved \a id.
+ \a obj must be the same object as used in the previous call
+ to QmlMetaProperty::save(). Only the bottom 24-bits are
+ used, the high bits can be set to any value.
+*/
+void QmlMetaProperty::restore(quint32 id, QObject *obj)
+{
+ *this = QmlMetaProperty();
+ d->object = obj;
+
+ id &= 0xFFFFFF;
+ d->type = id >> 16;
+ id &= 0xFFFF;
+
+ if (d->type & Attached) {
+ d->attachedFunc = id;
+ } else if (d->type & Property) {
+ QMetaPropertyEx p(obj->metaObject()->property(id));
+ d->prop = p;
+ d->propType = p.propertyType;
+ d->coreIdx = id;
+ } else if (d->type & SignalProperty || d->type & Signal) {
+ d->signal = obj->metaObject()->method(id);
+ d->coreIdx = id;
+ }
+}
+
+/*!
+ Return the QMetaMethod for this property if it is a SignalProperty,
+ otherwise returns an invalid QMetaMethod.
+*/
+QMetaMethod QmlMetaProperty::method() const
+{
+ return d->signal;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h
new file mode 100644
index 0000000..68b06e5
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLMETAPROPERTY_H
+#define QMLMETAPROPERTY_H
+
+#include <QtDeclarative/qfxglobal.h>
+#include <QMetaProperty>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QObject;
+class QmlBindableValue;
+class QStringList;
+class QVariant;
+struct QMetaObject;
+class QmlContext;
+
+class QmlMetaPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlMetaProperty
+{
+public:
+ enum PropertyCategory {
+ Unknown,
+ InvalidProperty,
+ Bindable,
+ List,
+ QmlList, //XXX
+ Object,
+ Normal
+ };
+ QmlMetaProperty();
+ QmlMetaProperty(QObject *);
+ QmlMetaProperty(QObject *, const QString &);
+ QmlMetaProperty(QObject *, QmlContext *);
+ QmlMetaProperty(QObject *, const QString &, QmlContext *);
+ QmlMetaProperty(const QmlMetaProperty &);
+ QmlMetaProperty &operator=(const QmlMetaProperty &);
+ QmlMetaProperty(QObject *, int, PropertyCategory = Unknown, QmlContext * = 0);
+ ~QmlMetaProperty();
+
+ static QStringList properties(QObject *);
+ QString name() const;
+
+ QVariant read() const;
+ void write(const QVariant &) const;
+ void emitSignal();
+
+ bool hasChangedNotifier() const;
+ bool needsChangedNotifier() const;
+ bool connectNotifier(QObject *dest, const char *slot) const;
+ bool connectNotifier(QObject *dest, int method) const;
+
+ quint32 save() const;
+ void restore(quint32, QObject *);
+
+ QMetaMethod method() const;
+
+ enum Type { Invalid = 0x00,
+ Property = 0x01,
+ SignalProperty = 0x02,
+ Signal = 0x04,
+ Default = 0x08,
+ Attached = 0x10 };
+
+ Type type() const;
+ bool isProperty() const;
+ bool isDefault() const;
+ bool isWritable() const;
+ bool isDesignable() const;
+ bool isValid() const;
+ QObject *object() const;
+
+ PropertyCategory propertyCategory() const;
+ static PropertyCategory propertyCategory(const QMetaProperty &);
+
+ int propertyType() const;
+ const char *propertyTypeName() const;
+
+ bool operator==(const QmlMetaProperty &) const;
+
+ const QMetaProperty &property() const;
+
+ QmlBindableValue *binding();
+ static int findSignal(const QObject *, const char *);
+
+ int coreIndex() const;
+private:
+ void initDefault(QObject *obj);
+ void initProperty(QObject *obj, const QString &name);
+ friend class QmlEnginePrivate;
+ QmlMetaPropertyPrivate *d;
+};
+typedef QList<QmlMetaProperty> QmlMetaProperties;
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLMETAPROPERTY_H
diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h
new file mode 100644
index 0000000..1ea38e9
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLMETAPROPERTY_P_H
+#define QMLMETAPROPERTY_P_H
+
+#include "qmlmetaproperty.h"
+
+class QmlContext;
+class QmlMetaPropertyPrivate
+{
+public:
+ QmlMetaPropertyPrivate()
+ : context(0), coreIdx(-1), type(QmlMetaProperty::Invalid), attachedFunc(-1),
+ object(0), propType(-1), category(QmlMetaProperty::Unknown) {}
+ QmlMetaPropertyPrivate(const QmlMetaPropertyPrivate &other)
+ : name(other.name), signal(other.signal), context(other.context),
+ coreIdx(other.coreIdx), type(other.type), attachedFunc(other.attachedFunc),
+ object(other.object), prop(other.prop), propType(other.propType),
+ category(other.category) {}
+
+ QString name;
+ QMetaMethod signal;
+ QmlContext *context;
+ int coreIdx;
+ uint type;
+ int attachedFunc;
+ QObject *object;
+ QMetaProperty prop;
+ int propType;
+
+ mutable QmlMetaProperty::PropertyCategory category;
+
+ QObject *attachedObject() const;
+ void findSignalInt(QObject *, const QString &);
+
+ int propertyType() const;
+ QmlMetaProperty::PropertyCategory propertyCategory() const;
+
+ void writeSignalProperty(const QVariant &);
+ void writeValueProperty(const QVariant &);
+};
+
+#endif // QMLMETAPROPERTY_P_H
+
diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp
new file mode 100644
index 0000000..7825e5c
--- /dev/null
+++ b/src/declarative/qml/qmlmetatype.cpp
@@ -0,0 +1,1144 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlmetatype.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qbitarray.h>
+#include <QtCore/qreadwritelock.h>
+#include <private/qmlproxymetaobject_p.h>
+
+#include <qmetatype.h>
+#include <qobjectdefs.h>
+#include <qdatetime.h>
+#include <qbytearray.h>
+#include <qreadwritelock.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvector.h>
+#include <qlocale.h>
+#include <QtCore/qcryptographichash.h>
+#include <private/qmlcustomparser_p.h>
+
+QT_BEGIN_NAMESPACE
+#ifdef QT_BOOTSTRAPPED
+# ifndef QT_NO_GEOM_VARIANT
+# define QT_NO_GEOM_VARIANT
+# endif
+#else
+# include <qbitarray.h>
+# include <qurl.h>
+# include <qvariant.h>
+#endif
+
+#ifndef QT_NO_GEOM_VARIANT
+# include <qsize.h>
+# include <qpoint.h>
+# include <qrect.h>
+# include <qline.h>
+#endif
+#define NS(x) QT_PREPEND_NAMESPACE(x)
+
+struct QmlMetaTypeData
+{
+ QList<QmlType *> types;
+ typedef QHash<int, QmlType *> Ids;
+ Ids idToType;
+ typedef QHash<QByteArray, QmlType *> Names;
+ Names nameToType;
+ typedef QHash<const QMetaObject *, QmlType *> MetaObjects;
+ MetaObjects metaObjectToType;
+ typedef QHash<int, QmlMetaType::StringConverter> StringConverters;
+ StringConverters stringConverters;
+
+ QBitArray objects;
+ QBitArray interfaces;
+ QBitArray qmllists;
+ QBitArray lists;
+};
+Q_GLOBAL_STATIC(QmlMetaTypeData, metaTypeData);
+Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock);
+
+class QmlTypePrivate
+{
+public:
+ QmlTypePrivate();
+
+ void init() const;
+
+ bool m_isInterface : 1;
+ const char *m_iid;
+ QByteArray m_name;
+ int m_typeId; int m_listId; int m_qmlListId;
+ QmlPrivate::Func m_opFunc;
+ const QMetaObject *m_baseMetaObject;
+ QmlAttachedPropertiesFunc m_attachedPropertiesFunc;
+ int m_parserStatusCast;
+ QmlPrivate::CreateFunc m_extFunc;
+ const QMetaObject *m_extMetaObject;
+ int m_index;
+ QmlCustomParser *m_customParser;
+ mutable volatile bool m_isSetup:1;
+ mutable QList<QmlProxyMetaObject::ProxyData> m_metaObjects;
+ mutable QByteArray m_hash;
+};
+
+QmlTypePrivate::QmlTypePrivate()
+: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_qmlListId(0),
+ m_opFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0),
+ m_parserStatusCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1),
+ m_customParser(0), m_isSetup(false)
+{
+}
+
+
+QmlType::QmlType(int type, int listType, int qmlListType,
+ QmlPrivate::Func opFunc, const char *iid, int index)
+: d(new QmlTypePrivate)
+{
+ d->m_isInterface = true;
+ d->m_iid = iid;
+ d->m_typeId = type;
+ d->m_listId = listType;
+ d->m_qmlListId = qmlListType;
+ d->m_opFunc = opFunc;
+ d->m_index = index;
+ d->m_isSetup = true;
+}
+
+QmlType::QmlType(int type, int listType, int qmlListType,
+ QmlPrivate::Func opFunc, const char *qmlName,
+ const QMetaObject *metaObject,
+ QmlAttachedPropertiesFunc attachedPropertiesFunc,
+ int parserStatusCast, QmlPrivate::CreateFunc extFunc,
+ const QMetaObject *extMetaObject, int index,
+ QmlCustomParser *customParser)
+: d(new QmlTypePrivate)
+{
+ d->m_name = qmlName;
+ d->m_typeId = type;
+ d->m_listId = listType;
+ d->m_qmlListId = qmlListType;
+ d->m_opFunc = opFunc;
+ d->m_baseMetaObject = metaObject;
+ d->m_attachedPropertiesFunc = attachedPropertiesFunc;
+ d->m_parserStatusCast = parserStatusCast;
+ d->m_extFunc = extFunc;
+ d->m_index = index;
+ d->m_customParser = customParser;
+
+ if (extMetaObject)
+ d->m_extMetaObject = extMetaObject;
+}
+
+QmlType::~QmlType()
+{
+ delete d;
+}
+
+void QmlTypePrivate::init() const
+{
+ if (m_isSetup) return;
+
+ QWriteLocker lock(metaTypeDataLock());
+ if (m_isSetup)
+ return;
+
+ // Setup extended meta object
+ // XXX - very inefficient
+ const QMetaObject *mo = m_baseMetaObject;
+ if (m_extFunc) {
+ QMetaObject *mmo = new QMetaObject;
+ *mmo = *m_extMetaObject;
+ mmo->d.superdata = mo;
+ QmlProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0 };
+ m_metaObjects << data;
+ }
+
+ mo = mo->d.superdata;
+ while(mo) {
+ QmlType *t = metaTypeData()->metaObjectToType.value(mo);
+ if (t) {
+ if (t->d->m_extFunc) {
+ QMetaObject *mmo = new QMetaObject;
+ *mmo = *t->d->m_extMetaObject;
+ mmo->d.superdata = m_baseMetaObject;
+ if (!m_metaObjects.isEmpty())
+ m_metaObjects.last().metaObject->d.superdata = mmo;
+ QmlProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0 };
+ m_metaObjects << data;
+ }
+ }
+ mo = mo->d.superdata;
+ }
+
+ for (int ii = 0; ii < m_metaObjects.count(); ++ii)
+ m_metaObjects[ii].propertyOffset =
+ m_metaObjects.at(ii).metaObject->propertyOffset();
+
+ // Calculate hash
+ QByteArray hashData;
+
+ const QMetaObject *myMetaObject = m_metaObjects.isEmpty()?m_baseMetaObject:m_metaObjects.first().metaObject;
+
+ for (int ii = 0; ii < myMetaObject->propertyCount(); ++ii) {
+ QMetaProperty prop = myMetaObject->property(ii);
+ hashData.append(prop.type());
+ hashData.append("|");
+ hashData.append(prop.name());
+ hashData.append("|");
+ }
+
+ for (int ii = 0; ii < myMetaObject->methodCount(); ++ii) {
+ QMetaMethod method = myMetaObject->method(ii);
+ hashData.append(method.signature());
+ hashData.append("|");
+ }
+
+ m_hash = QCryptographicHash::hash(hashData, QCryptographicHash::Md5);
+
+ m_isSetup = true;
+ lock.unlock();
+}
+
+QByteArray QmlType::typeName() const
+{
+ if (d->m_baseMetaObject)
+ return d->m_baseMetaObject->className();
+ else
+ return QByteArray();
+}
+
+QByteArray QmlType::qmlTypeName() const
+{
+ return d->m_name;
+}
+
+QByteArray QmlType::hash() const
+{
+ d->init();
+
+ return d->m_hash;
+}
+
+QObject *QmlType::create() const
+{
+ d->init();
+
+ QVariant v;
+ QObject *rv = 0;
+ d->m_opFunc(QmlPrivate::Create, 0, v, v, (void **)&rv);
+
+ if (rv && !d->m_metaObjects.isEmpty())
+ (void *)new QmlProxyMetaObject(rv, &d->m_metaObjects);
+
+ return rv;
+}
+
+QmlCustomParser *QmlType::customParser() const
+{
+ return d->m_customParser;
+}
+
+bool QmlType::isInterface() const
+{
+ return d->m_isInterface;
+}
+
+int QmlType::typeId() const
+{
+ return d->m_typeId;
+}
+
+int QmlType::qListTypeId() const
+{
+ return d->m_listId;
+}
+
+int QmlType::qmlListTypeId() const
+{
+ return d->m_qmlListId;
+}
+
+void QmlType::listClear(const QVariant &list)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ QVariant arg;
+ d->m_opFunc(QmlPrivate::Clear, 0, list, arg, 0);
+}
+
+void QmlType::listAppend(const QVariant &list, const QVariant &item)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ d->m_opFunc(QmlPrivate::Append, 0, list, item, 0);
+}
+
+QVariant QmlType::listAt(const QVariant &list, int idx)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ QVariant rv;
+ void *ptr = (void *)&rv;
+ d->m_opFunc(QmlPrivate::Value, idx, list, QVariant(), &ptr);
+ return rv;
+}
+
+int QmlType::listCount(const QVariant &list)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ return d->m_opFunc(QmlPrivate::Length, 0, list, QVariant(), 0);
+}
+
+const QMetaObject *QmlType::metaObject() const
+{
+ d->init();
+
+ if (d->m_metaObjects.isEmpty())
+ return d->m_baseMetaObject;
+ else
+ return d->m_metaObjects.first().metaObject;
+
+}
+
+const QMetaObject *QmlType::baseMetaObject() const
+{
+ return d->m_baseMetaObject;
+}
+
+QmlAttachedPropertiesFunc QmlType::attachedPropertiesFunction() const
+{
+ return d->m_attachedPropertiesFunc;
+}
+
+int QmlType::parserStatusCast() const
+{
+ return d->m_parserStatusCast;
+}
+
+QVariant QmlType::fromObject(QObject *obj) const
+{
+ QVariant rv;
+ QVariant *v_ptr = &rv;
+ QVariant vobj = QVariant::fromValue(obj);
+ d->m_opFunc(QmlPrivate::FromObject, 0, QVariant(), vobj, (void **)&v_ptr);
+ return rv;
+}
+
+const char *QmlType::interfaceIId() const
+{
+ return d->m_iid;
+}
+
+int QmlType::index() const
+{
+ return d->m_index;
+}
+
+int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id,
+ QmlPrivate::Func listFunction,
+ const char *iid)
+{
+ QWriteLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ int index = data->types.count();
+
+ QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId,
+ listFunction, iid, index);
+
+ data->types.append(type);
+ data->idToType.insert(type->typeId(), type);
+ data->idToType.insert(type->qListTypeId(), type);
+ data->idToType.insert(type->qmlListTypeId(), type);
+ data->nameToType.insert(type->qmlTypeName(), type);
+
+ if (data->interfaces.size() < id.typeId)
+ data->interfaces.resize(id.typeId + 16);
+ if (data->qmllists.size() < id.qmlListId)
+ data->qmllists.resize(id.qmlListId + 16);
+ if (data->lists.size() < id.listId)
+ data->lists.resize(id.listId + 16);
+ data->interfaces.setBit(id.typeId, true);
+ data->qmllists.setBit(id.qmlListId, true);
+ data->lists.setBit(id.listId, true);
+
+ return index;
+}
+
+int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func, const char *cname, const QMetaObject *mo, QmlAttachedPropertiesFunc attach, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser)
+{
+ Q_UNUSED(object);
+ QWriteLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QString name = QLatin1String(cname);
+ for (int ii = 0; ii < name.count(); ++ii) {
+ if (!name.at(ii).isLetterOrNumber()) {
+ qWarning("QmlMetaType: Invalid QML name %s", cname);
+ return -1;
+ }
+ }
+
+ int index = data->types.count();
+
+ QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId,
+ func, cname, mo, attach, pStatus, extFunc,
+ extmo, index, parser);
+
+ data->types.append(type);
+ data->idToType.insert(type->typeId(), type);
+ data->idToType.insert(type->qListTypeId(), type);
+ data->idToType.insert(type->qmlListTypeId(), type);
+
+ if (!type->qmlTypeName().isEmpty())
+ data->nameToType.insert(type->qmlTypeName(), type);
+
+ data->metaObjectToType.insert(type->baseMetaObject(), type);
+
+ if (data->objects.size() <= id.typeId)
+ data->objects.resize(id.typeId + 16);
+ if (data->qmllists.size() <= id.qmlListId)
+ data->qmllists.resize(id.qmlListId + 16);
+ if (data->lists.size() <= id.listId)
+ data->lists.resize(id.listId + 16);
+ data->objects.setBit(id.typeId, true);
+ data->qmllists.setBit(id.qmlListId, true);
+ data->lists.setBit(id.listId, true);
+
+ return index;
+}
+
+int QmlMetaType::qmlParserStatusCast(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ if (type && type->typeId() == userType)
+ return type->parserStatusCast();
+ else
+ return -1;
+}
+
+QObject *QmlMetaType::toQObject(const QVariant &v)
+{
+ if (!isObject(v.userType()))
+ return 0;
+
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ QObject *rv = *(QObject **)v.constData();
+ return rv;
+}
+
+/*
+ Returns the item type for a list of type \a id.
+ */
+int QmlMetaType::listType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ if (type && type->qListTypeId() == id)
+ return type->typeId();
+ else
+ return 0;
+}
+
+/*
+ Returns the item type for a qml list of type \a id.
+ */
+int QmlMetaType::qmlListType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ if (type && type->qmlListTypeId() == id)
+ return type->typeId();
+ else
+ return 0;
+}
+
+bool QmlMetaType::clear(const QVariant &list)
+{
+ int userType = list.userType();
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if (type && type->qListTypeId() == userType) {
+ type->listClear(list);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QmlMetaType::append(const QVariant &list, const QVariant &item)
+{
+ int userType = list.userType();
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if (type && type->qListTypeId() == userType &&
+ item.userType() == type->typeId()) {
+ type->listAppend(list, item);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+QObject *QmlMetaType::create(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ lock.unlock();
+
+ QmlType *type = data->nameToType.value(name);
+ if (type)
+ return type->create();
+ else
+ return 0;
+}
+
+QVariant QmlMetaType::fromObject(QObject *obj, int typeId)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->idToType.value(typeId);
+ if (type && type->typeId() == typeId)
+ return type->fromObject(obj);
+ else
+ return QVariant();
+}
+
+const QMetaObject *QmlMetaType::rawMetaObjectForType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->idToType.value(id);
+ if (type && type->typeId() == id)
+ return type->baseMetaObject();
+ else
+ return 0;
+}
+
+const QMetaObject *QmlMetaType::rawMetaObjectForType(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->nameToType.value(name);
+ if (type)
+ return type->baseMetaObject();
+ else
+ return 0;
+}
+
+const QMetaObject *QmlMetaType::metaObjectForType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ lock.unlock();
+
+ if (type && type->typeId() == id)
+ return type->metaObject();
+ else
+ return 0;
+}
+
+const QMetaObject *QmlMetaType::metaObjectForType(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->nameToType.value(name);
+ lock.unlock();
+
+ if (type)
+ return type->metaObject();
+ else
+ return 0;
+}
+
+int QmlMetaType::type(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->nameToType.value(name);
+ if (type)
+ return type->typeId();
+ else
+ return 0;
+}
+
+int QmlMetaType::attachedPropertiesFuncId(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->nameToType.value(name);
+ if (type && type->attachedPropertiesFunction())
+ return type->index();
+ else
+ return -1;
+}
+
+int QmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->metaObjectToType.value(mo);
+ if (type && type->attachedPropertiesFunction())
+ return type->index();
+ else
+ return -1;
+}
+
+QmlAttachedPropertiesFunc QmlMetaType::attachedPropertiesFuncById(int id)
+{
+ if (id < 0)
+ return 0;
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return data->types.at(id)->attachedPropertiesFunction();
+}
+
+QmlAttachedPropertiesFunc
+QmlMetaType::attachedPropertiesFunc(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->nameToType.value(name);
+ if (type)
+ return type->attachedPropertiesFunction();
+ else
+ return 0;
+}
+
+QMetaProperty QmlMetaType::defaultProperty(const QMetaObject *metaObject)
+{
+ int idx = metaObject->indexOfClassInfo("DefaultProperty");
+ if (-1 == idx)
+ return QMetaProperty();
+
+ QMetaClassInfo info = metaObject->classInfo(idx);
+ if (!info.value())
+ return QMetaProperty();
+
+ idx = metaObject->indexOfProperty(info.value());
+ if (-1 == idx)
+ return QMetaProperty();
+
+ return metaObject->property(idx);
+}
+
+QMetaProperty QmlMetaType::defaultProperty(QObject *obj)
+{
+ if (!obj)
+ return QMetaProperty();
+
+ const QMetaObject *metaObject = obj->metaObject();
+ return defaultProperty(metaObject);
+}
+
+QMetaMethod QmlMetaType::defaultMethod(const QMetaObject *metaObject)
+{
+ int idx = metaObject->indexOfClassInfo("DefaultMethod");
+ if (-1 == idx)
+ return QMetaMethod();
+
+ QMetaClassInfo info = metaObject->classInfo(idx);
+ if (!info.value())
+ return QMetaMethod();
+
+ idx = metaObject->indexOfMethod(info.value());
+ if (-1 == idx)
+ return QMetaMethod();
+
+ return metaObject->method(idx);
+}
+
+QMetaMethod QmlMetaType::defaultMethod(QObject *obj)
+{
+ if (!obj)
+ return QMetaMethod();
+
+ const QMetaObject *metaObject = obj->metaObject();
+ return defaultMethod(metaObject);
+}
+
+/*!
+ */
+QMetaProperty QmlMetaType::property(QObject *obj, const QByteArray &bname)
+{
+ return property(obj, bname.constData());
+}
+
+/*!
+ */
+QMetaProperty QmlMetaType::property(QObject *obj, const char *name)
+{
+ if (!obj)
+ return QMetaProperty();
+
+ const QMetaObject *metaObject = obj->metaObject();
+
+ int idx = metaObject->indexOfProperty(name);
+ if (-1 == idx)
+ return QMetaProperty();
+
+ return metaObject->property(idx);
+}
+
+bool QmlMetaType::isObject(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
+}
+
+bool QmlMetaType::isInterface(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
+}
+
+const char *QmlMetaType::interfaceIId(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if (type && type->isInterface() && type->typeId() == userType)
+ return type->interfaceIId();
+ else
+ return 0;
+}
+
+bool QmlMetaType::isObject(const QMetaObject *mo)
+{
+ while(mo) {
+ if (mo == &QObject::staticMetaObject)
+ return true;
+ mo = mo->superClass();
+ }
+ return false;
+}
+
+bool QmlMetaType::isQmlList(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->qmllists.size() && data->qmllists.testBit(userType);
+}
+
+bool QmlMetaType::isList(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
+}
+
+bool QmlMetaType::isList(const QVariant &v)
+{
+ return (v.type() == QVariant::UserType && isList(v.userType()));
+}
+
+int QmlMetaType::listCount(const QVariant &v)
+{
+ int userType = v.userType();
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+
+ if (type && type->qListTypeId() == userType)
+ return type->listCount(v);
+ else
+ return 0;
+}
+
+QVariant QmlMetaType::listAt(const QVariant &v, int idx)
+{
+ int userType = v.userType();
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+
+ if (type && type->qListTypeId() == userType)
+ return type->listAt(v, idx);
+ else
+ return 0;
+}
+
+/*!
+ A custom string convertor allows you to specify a function pointer that
+ returns a variant of \a type. For example, if you have written your own icon
+ class that you want to support as an object property assignable in QML:
+
+ \code
+ int type = qRegisterMetaType<SuperIcon>("SuperIcon");
+ QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
+ \endcode
+
+ The function pointer must be of the form:
+ \code
+ QVariant (*StringConverter)(const QString &);
+ \endcode
+ */
+void QmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
+{
+ QWriteLocker lock(metaTypeDataLock());
+
+ QmlMetaTypeData *data = metaTypeData();
+ if (data->stringConverters.contains(type))
+ return;
+ data->stringConverters.insert(type, converter);
+}
+
+/*!
+ Return the custom string converter for \a type, previously installed through
+ registerCustomStringConverter()
+ */
+QmlMetaType::StringConverter QmlMetaType::customStringConverter(int type)
+{
+ QReadLocker lock(metaTypeDataLock());
+
+ QmlMetaTypeData *data = metaTypeData();
+ return data->stringConverters.value(type);
+}
+
+QmlType *QmlMetaType::qmlType(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->nameToType.value(name);
+}
+
+QList<QByteArray> QmlMetaType::qmlTypeNames()
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->nameToType.keys();
+}
+
+/*!
+ Copies \a copy into \a data, assuming they both are of type \a type. If
+ \a copy is zero, a default type is copied. Returns true if the copy was
+ successful and false if not.
+
+ \note This should move into QMetaType once complete
+
+*/
+bool QmlMetaType::copy(int type, void *data, const void *copy)
+{
+ if (copy) {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ *static_cast<void **>(data) = *static_cast<void* const *>(copy);
+ return true;
+ case QMetaType::Long:
+ *static_cast<long *>(data) = *static_cast<const long*>(copy);
+ return true;
+ case QMetaType::Int:
+ *static_cast<int *>(data) = *static_cast<const int*>(copy);
+ return true;
+ case QMetaType::Short:
+ *static_cast<short *>(data) = *static_cast<const short*>(copy);
+ return true;
+ case QMetaType::Char:
+ *static_cast<char *>(data) = *static_cast<const char*>(copy);
+ return true;
+ case QMetaType::ULong:
+ *static_cast<ulong *>(data) = *static_cast<const ulong*>(copy);
+ return true;
+ case QMetaType::UInt:
+ *static_cast<uint *>(data) = *static_cast<const uint*>(copy);
+ return true;
+ case QMetaType::LongLong:
+ *static_cast<qlonglong *>(data) = *static_cast<const qlonglong*>(copy);
+ return true;
+ case QMetaType::ULongLong:
+ *static_cast<qulonglong *>(data) = *static_cast<const qulonglong*>(copy);
+ return true;
+ case QMetaType::UShort:
+ *static_cast<ushort *>(data) = *static_cast<const ushort*>(copy);
+ return true;
+ case QMetaType::UChar:
+ *static_cast<uchar *>(data) = *static_cast<const uchar*>(copy);
+ return true;
+ case QMetaType::Bool:
+ *static_cast<bool *>(data) = *static_cast<const bool*>(copy);
+ return true;
+ case QMetaType::Float:
+ *static_cast<float *>(data) = *static_cast<const float*>(copy);
+ return true;
+ case QMetaType::Double:
+ *static_cast<double *>(data) = *static_cast<const double*>(copy);
+ return true;
+ case QMetaType::QChar:
+ *static_cast<NS(QChar) *>(data) = *static_cast<const NS(QChar)*>(copy);
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ *static_cast<NS(QVariantMap) *>(data) = *static_cast<const NS(QVariantMap)*>(copy);
+ return true;
+ case QMetaType::QVariantHash:
+ *static_cast<NS(QVariantHash) *>(data) = *static_cast<const NS(QVariantHash)*>(copy);
+ return true;
+ case QMetaType::QVariantList:
+ *static_cast<NS(QVariantList) *>(data) = *static_cast<const NS(QVariantList)*>(copy);
+ return true;
+#endif
+ case QMetaType::QByteArray:
+ *static_cast<NS(QByteArray) *>(data) = *static_cast<const NS(QByteArray)*>(copy);
+ return true;
+ case QMetaType::QString:
+ *static_cast<NS(QString) *>(data) = *static_cast<const NS(QString)*>(copy);
+ return true;
+ case QMetaType::QStringList:
+ *static_cast<NS(QStringList) *>(data) = *static_cast<const NS(QStringList)*>(copy);
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ *static_cast<NS(QBitArray) *>(data) = *static_cast<const NS(QBitArray)*>(copy);
+ return true;
+#endif
+ case QMetaType::QDate:
+ *static_cast<NS(QDate) *>(data) = *static_cast<const NS(QDate)*>(copy);
+ return true;
+ case QMetaType::QTime:
+ *static_cast<NS(QTime) *>(data) = *static_cast<const NS(QTime)*>(copy);
+ return true;
+ case QMetaType::QDateTime:
+ *static_cast<NS(QDateTime) *>(data) = *static_cast<const NS(QDateTime)*>(copy);
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ *static_cast<NS(QUrl) *>(data) = *static_cast<const NS(QUrl)*>(copy);
+ return true;
+#endif
+ case QMetaType::QLocale:
+ *static_cast<NS(QLocale) *>(data) = *static_cast<const NS(QLocale)*>(copy);
+ return true;
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ *static_cast<NS(QRect) *>(data) = *static_cast<const NS(QRect)*>(copy);
+ return true;
+ case QMetaType::QRectF:
+ *static_cast<NS(QRectF) *>(data) = *static_cast<const NS(QRectF)*>(copy);
+ return true;
+ case QMetaType::QSize:
+ *static_cast<NS(QSize) *>(data) = *static_cast<const NS(QSize)*>(copy);
+ return true;
+ case QMetaType::QSizeF:
+ *static_cast<NS(QSizeF) *>(data) = *static_cast<const NS(QSizeF)*>(copy);
+ return true;
+ case QMetaType::QLine:
+ *static_cast<NS(QLine) *>(data) = *static_cast<const NS(QLine)*>(copy);
+ return true;
+ case QMetaType::QLineF:
+ *static_cast<NS(QLineF) *>(data) = *static_cast<const NS(QLineF)*>(copy);
+ return true;
+ case QMetaType::QPoint:
+ *static_cast<NS(QPoint) *>(data) = *static_cast<const NS(QPoint)*>(copy);
+ return true;
+ case QMetaType::QPointF:
+ *static_cast<NS(QPointF) *>(data) = *static_cast<const NS(QPointF)*>(copy);
+ return true;
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ *static_cast<NS(QRegExp) *>(data) = *static_cast<const NS(QRegExp)*>(copy);
+ return true;
+#endif
+ case QMetaType::Void:
+ return true;
+ default:
+ ;
+ }
+ } else {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ *static_cast<void **>(data) = 0;
+ return true;
+ case QMetaType::Long:
+ *static_cast<long *>(data) = long(0);
+ return true;
+ case QMetaType::Int:
+ *static_cast<int *>(data) = int(0);
+ return true;
+ case QMetaType::Short:
+ *static_cast<short *>(data) = short(0);
+ return true;
+ case QMetaType::Char:
+ *static_cast<char *>(data) = char(0);
+ return true;
+ case QMetaType::ULong:
+ *static_cast<ulong *>(data) = ulong(0);
+ return true;
+ case QMetaType::UInt:
+ *static_cast<uint *>(data) = uint(0);
+ return true;
+ case QMetaType::LongLong:
+ *static_cast<qlonglong *>(data) = qlonglong(0);
+ return true;
+ case QMetaType::ULongLong:
+ *static_cast<qulonglong *>(data) = qulonglong(0);
+ return true;
+ case QMetaType::UShort:
+ *static_cast<ushort *>(data) = ushort(0);
+ return true;
+ case QMetaType::UChar:
+ *static_cast<uchar *>(data) = uchar(0);
+ return true;
+ case QMetaType::Bool:
+ *static_cast<bool *>(data) = bool(false);
+ return true;
+ case QMetaType::Float:
+ *static_cast<float *>(data) = float(0);
+ return true;
+ case QMetaType::Double:
+ *static_cast<double *>(data) = double();
+ return true;
+ case QMetaType::QChar:
+ *static_cast<NS(QChar) *>(data) = NS(QChar)();
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ *static_cast<NS(QVariantMap) *>(data) = NS(QVariantMap)();
+ return true;
+ case QMetaType::QVariantHash:
+ *static_cast<NS(QVariantHash) *>(data) = NS(QVariantHash)();
+ return true;
+ case QMetaType::QVariantList:
+ *static_cast<NS(QVariantList) *>(data) = NS(QVariantList)();
+ return true;
+#endif
+ case QMetaType::QByteArray:
+ *static_cast<NS(QByteArray) *>(data) = NS(QByteArray)();
+ return true;
+ case QMetaType::QString:
+ *static_cast<NS(QString) *>(data) = NS(QString)();
+ return true;
+ case QMetaType::QStringList:
+ *static_cast<NS(QStringList) *>(data) = NS(QStringList)();
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ *static_cast<NS(QBitArray) *>(data) = NS(QBitArray)();
+ return true;
+#endif
+ case QMetaType::QDate:
+ *static_cast<NS(QDate) *>(data) = NS(QDate)();
+ return true;
+ case QMetaType::QTime:
+ *static_cast<NS(QTime) *>(data) = NS(QTime)();
+ return true;
+ case QMetaType::QDateTime:
+ *static_cast<NS(QDateTime) *>(data) = NS(QDateTime)();
+ return true;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ *static_cast<NS(QUrl) *>(data) = NS(QUrl)();
+ return true;
+#endif
+ case QMetaType::QLocale:
+ *static_cast<NS(QLocale) *>(data) = NS(QLocale)();
+ return true;
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ *static_cast<NS(QRect) *>(data) = NS(QRect)();
+ return true;
+ case QMetaType::QRectF:
+ *static_cast<NS(QRectF) *>(data) = NS(QRectF)();
+ return true;
+ case QMetaType::QSize:
+ *static_cast<NS(QSize) *>(data) = NS(QSize)();
+ return true;
+ case QMetaType::QSizeF:
+ *static_cast<NS(QSizeF) *>(data) = NS(QSizeF)();
+ return true;
+ case QMetaType::QLine:
+ *static_cast<NS(QLine) *>(data) = NS(QLine)();
+ return true;
+ case QMetaType::QLineF:
+ *static_cast<NS(QLineF) *>(data) = NS(QLineF)();
+ return true;
+ case QMetaType::QPoint:
+ *static_cast<NS(QPoint) *>(data) = NS(QPoint)();
+ return true;
+ case QMetaType::QPointF:
+ *static_cast<NS(QPointF) *>(data) = NS(QPointF)();
+ return true;
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ *static_cast<NS(QRegExp) *>(data) = NS(QRegExp)();
+ return true;
+#endif
+ case QMetaType::Void:
+ return true;
+ default:
+ ;
+ }
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h
new file mode 100644
index 0000000..7ab01a5
--- /dev/null
+++ b/src/declarative/qml/qmlmetatype.h
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLMETATYPE_H
+#define QMLMETATYPE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qbitarray.h>
+#include <QtDeclarative/qmlprivate.h>
+#include <QtDeclarative/qmlparserstatus.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlType;
+class QmlCustomParser;
+class Q_DECLARATIVE_EXPORT QmlMetaType
+{
+public:
+ static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, const QMetaObject *, QmlAttachedPropertiesFunc, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *);
+ static int registerInterface(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *);
+
+ static bool copy(int type, void *data, const void *copy = 0);
+
+ static QmlType *qmlType(const QByteArray &);
+ static QList<QByteArray> qmlTypeNames();
+
+ static QMetaProperty defaultProperty(const QMetaObject *);
+ static QMetaProperty defaultProperty(QObject *);
+ static QMetaMethod defaultMethod(const QMetaObject *);
+ static QMetaMethod defaultMethod(QObject *);
+ static QMetaProperty property(QObject *, const QByteArray &);
+ static QMetaProperty property(QObject *, const char *);
+ static QObject *toQObject(const QVariant &);
+ static int qmlParserStatusCast(int);
+ static int listType(int);
+ static int type(const QByteArray &);
+ static int type(const QString &);
+ static bool clear(const QVariant &);
+ static bool append(const QVariant &, const QVariant &);
+ static QVariant fromObject(QObject *, int type);
+ static QObject *create(const QByteArray &);
+ static const QMetaObject *rawMetaObjectForType(const QByteArray &);
+ static const QMetaObject *rawMetaObjectForType(int);
+ static const QMetaObject *metaObjectForType(const QByteArray &);
+ static const QMetaObject *metaObjectForType(int);
+ static int attachedPropertiesFuncId(const QByteArray &);
+ static int attachedPropertiesFuncId(const QMetaObject *);
+ static QmlAttachedPropertiesFunc attachedPropertiesFuncById(int);
+ static QmlAttachedPropertiesFunc attachedPropertiesFunc(const QByteArray &);
+
+ static bool isInterface(int);
+ static const char *interfaceIId(int);
+ static bool isObject(int);
+ static bool isObject(const QMetaObject *);
+ static bool isList(int);
+ static bool isList(const QVariant &);
+ static bool isQmlList(int);
+ static int qmlListType(int);
+ static int listCount(const QVariant &);
+ static QVariant listAt(const QVariant &, int);
+
+ typedef QVariant (*StringConverter)(const QString &);
+ static void registerCustomStringConverter(int, StringConverter);
+ static StringConverter customStringConverter(int);
+};
+
+class QmlTypePrivate;
+class QmlType
+{
+public:
+ QByteArray typeName() const;
+ QByteArray qmlTypeName() const;
+
+ QByteArray hash() const;
+
+ QObject *create() const;
+
+ QmlCustomParser *customParser() const;
+
+ bool isInterface() const;
+ int typeId() const;
+ int qListTypeId() const;
+ int qmlListTypeId() const;
+
+ void listClear(const QVariant &);
+ void listAppend(const QVariant &, const QVariant &);
+ QVariant listAt(const QVariant &, int);
+ int listCount(const QVariant &);
+
+ const QMetaObject *metaObject() const;
+ const QMetaObject *baseMetaObject() const;
+
+ QmlAttachedPropertiesFunc attachedPropertiesFunction() const;
+
+ int parserStatusCast() const;
+ QVariant fromObject(QObject *) const;
+ const char *interfaceIId() const;
+
+ int index() const;
+private:
+ friend class QmlMetaType;
+ friend class QmlTypePrivate;
+ QmlType(int, int, int, QmlPrivate::Func, const char *, int);
+ QmlType(int, int, int, QmlPrivate::Func, const char *, const QMetaObject *, QmlAttachedPropertiesFunc, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *);
+ ~QmlType();
+
+ QmlTypePrivate *d;
+};
+
+template<typename T>
+int qmlRegisterType(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op<T>, 0,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ 0, 0, 0);
+}
+
+template<typename T>
+int qmlRegisterType(const char *qmlName, const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>, qmlName,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ 0, 0, 0);
+}
+
+template<typename T, typename E>
+int qmlRegisterExtendedType(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ QmlAttachedPropertiesFunc attached =
+ QmlPrivate::attachedPropertiesFunc<E>();
+ if (!attached)
+ attached = QmlPrivate::attachedPropertiesFunc<T>();
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op<T>, 0,
+ &T::staticMetaObject, attached,
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ &QmlPrivate::CreateParent<E>::create, &E::staticMetaObject, 0);
+}
+
+template<typename T, typename E>
+int qmlRegisterExtendedType(const char *qmlName, const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ QmlAttachedPropertiesFunc attached =
+ QmlPrivate::attachedPropertiesFunc<E>();
+ if (!attached)
+ attached = QmlPrivate::attachedPropertiesFunc<T>();
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>,
+ qmlName,
+ &T::staticMetaObject,
+ attached,
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ &QmlPrivate::CreateParent<E>::create,
+ &E::staticMetaObject, 0);
+}
+
+template<typename T>
+int qmlRegisterInterface(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerInterface(ids,
+ QmlPrivate::list_interface_op<T>,
+ qobject_interface_iid<T *>());
+}
+
+template<typename T>
+int qmlRegisterCustomType(const char *qmlName, const char *typeName, QmlCustomParser *parser)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>, qmlName,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ 0, 0, parser);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLMETATYPE_H
+
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
new file mode 100644
index 0000000..bafdb02
--- /dev/null
+++ b/src/declarative/qml/qmlparser.cpp
@@ -0,0 +1,335 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlparser_p.h"
+#include <QStack>
+#include <qmlpropertyvaluesource.h>
+#include <QColor>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <private/qmlvme_p.h>
+#include <qmlbindablevalue.h>
+#include <qfxperf.h>
+#include <qml.h>
+#include "private/qmlcomponent_p.h"
+#include <qmlcomponent.h>
+#include <qmlbasicscript.h>
+#include "private/qmetaobjectbuilder_p.h"
+#include <private/qmlvmemetaobject_p.h>
+#include <private/qmlcompiler_p.h>
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlParser;
+
+QmlParser::Object::Object()
+: type(-1), metatype(0), extObjectData(0), defaultProperty(0)
+{
+}
+
+QmlParser::Object::~Object()
+{
+ if (defaultProperty) defaultProperty->release();
+ foreach(Property *prop, properties)
+ prop->release();
+}
+
+const QMetaObject *Object::metaObject() const
+{
+ if (extObjectData && metatype)
+ return &extObject;
+ else
+ return metatype;
+}
+
+QmlParser::Property *Object::getDefaultProperty()
+{
+ if (!defaultProperty)
+ defaultProperty = new Property;
+ return defaultProperty;
+}
+
+Property *QmlParser::Object::getProperty(const QByteArray &name, bool create)
+{
+ if (!properties.contains(name)) {
+ if (create)
+ properties.insert(name, new Property(name));
+ else
+ return 0;
+ }
+ return properties[name];
+}
+
+QmlParser::Object::DynamicProperty::DynamicProperty()
+: isDefaultProperty(false), type(Variant), defaultValue(0)
+{
+}
+
+QmlParser::Object::DynamicProperty::DynamicProperty(const DynamicProperty &o)
+: isDefaultProperty(o.isDefaultProperty),
+ type(o.type),
+ name(o.name),
+ onValueChanged(o.onValueChanged),
+ defaultValue(o.defaultValue)
+{
+}
+
+QmlParser::Object::DynamicSignal::DynamicSignal()
+{
+}
+
+QmlParser::Object::DynamicSignal::DynamicSignal(const DynamicSignal &o)
+: name(o.name)
+{
+}
+
+QmlParser::Object::DynamicSlot::DynamicSlot()
+{
+}
+
+QmlParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o)
+: name(o.name), body(o.body)
+{
+}
+
+void QmlParser::Object::dump(int indent) const
+{
+ QByteArray ba(indent * 4, ' ');
+ if (type != -1) {
+ qWarning() << ba.constData() << "Object:" << typeName;
+ } else {
+ qWarning() << ba.constData() << "Object: fetched";
+ }
+
+ for (QHash<QByteArray, Property *>::ConstIterator iter = properties.begin();
+ iter != properties.end();
+ ++iter) {
+ qWarning() << ba.constData() << " Property" << iter.key();
+ (*iter)->dump(indent + 1);
+ }
+
+ if (defaultProperty) {
+ qWarning() << ba.constData() << " Default property";
+ defaultProperty->dump(indent + 1);
+ }
+}
+
+QmlParser::Property::Property()
+: type(0), index(-1), value(0), isDefault(true)
+{
+}
+
+QmlParser::Property::Property(const QByteArray &n)
+: type(0), index(-1), value(0), name(n), isDefault(false)
+{
+}
+
+QmlParser::Property::~Property()
+{
+ foreach(Value *value, values)
+ value->release();
+ if (value) value->release();
+}
+
+Object *QmlParser::Property::getValue()
+{
+ if (!value) value = new Object;
+ return value;
+}
+
+void QmlParser::Property::addValue(Value *v)
+{
+ values << v;
+}
+
+void QmlParser::Property::dump(int indent) const
+{
+ QByteArray ba(indent * 4, ' ');
+ for (int ii = 0; ii < values.count(); ++ii)
+ values.at(ii)->dump(indent);
+ if (value)
+ value->dump(indent);
+}
+
+QmlParser::Value::Value()
+: type(Unknown), object(0)
+{
+}
+
+QmlParser::Value::~Value()
+{
+ if (object) object->release();
+}
+
+void QmlParser::Value::dump(int indent) const
+{
+ QByteArray type;
+ switch(this->type) {
+ default:
+ case Value::Unknown:
+ type = "Unknown";
+ break;
+ case Value::Literal:
+ type = "Literal";
+ break;
+ case Value::PropertyBinding:
+ type = "PropertyBinding";
+ break;
+ case Value::ValueSource:
+ type = "ValueSource";
+ break;
+ case Value::CreatedObject:
+ type = "CreatedObject";
+ break;
+ case Value::SignalObject:
+ type = "SignalObject";
+ break;
+ case Value::SignalExpression:
+ type = "SignalExpression";
+ break;
+ case Value::Component:
+ type = "Component";
+ break;
+ case Value::Id:
+ type = "Id";
+ break;
+ }
+
+ QByteArray primType;
+ switch(this->value.type()) {
+ default:
+ case Variant::Invalid:
+ primType = "Invalid";
+ break;
+ case Variant::Boolean:
+ primType = "Boolean";
+ break;
+ case Variant::Number:
+ primType = "Number";
+ break;
+ case Variant::String:
+ primType = "String";
+ break;
+ case Variant::Script:
+ primType = "Script";
+ break;
+ }
+
+ QByteArray ba(indent * 4, ' ');
+ if (object) {
+ qWarning() << ba.constData() << "Value (" << type << "):";
+ object->dump(indent + 1);
+ } else {
+ qWarning() << ba.constData() << "Value (" << type << "):" << primType.constData() << primitive();
+ }
+}
+
+QmlParser::Variant::Variant()
+: t(Invalid) {}
+
+QmlParser::Variant::Variant(const Variant &o)
+: t(o.t), d(o.d), s(o.s)
+{
+}
+
+QmlParser::Variant::Variant(bool v)
+: t(Boolean), b(v)
+{
+}
+
+QmlParser::Variant::Variant(double v)
+: t(Number), d(v)
+{
+}
+
+QmlParser::Variant::Variant(const QString &v, Type type)
+: t(type), s(v)
+{
+ Q_ASSERT(type == String || type == Script);
+}
+
+QmlParser::Variant &QmlParser::Variant::operator=(const Variant &o)
+{
+ t = o.t;
+ d = o.d;
+ s = o.s;
+ return *this;
+}
+
+QmlParser::Variant::Type QmlParser::Variant::type() const
+{
+ return t;
+}
+
+bool QmlParser::Variant::asBoolean() const
+{
+ return b;
+}
+
+QString QmlParser::Variant::asString() const
+{
+ return s;
+}
+
+double QmlParser::Variant::asNumber() const
+{
+ return d;
+}
+
+QString QmlParser::Variant::asScript() const
+{
+ switch(type()) {
+ default:
+ case Invalid:
+ return QString();
+ case Boolean:
+ return b?QLatin1String("true"):QLatin1String("false");
+ case Number:
+ return QString::number(d);
+ case String:
+ case Script:
+ return s;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
new file mode 100644
index 0000000..f25a76b
--- /dev/null
+++ b/src/declarative/qml/qmlparser_p.h
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPARSER_P_H
+#define QMLPARSER_P_H
+
+#include <QByteArray>
+#include <QList>
+#include <qml.h>
+#include <private/qmlrefcount_p.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+/*
+ XXX
+
+ These types are created (and owned) by the QmlXmlParser and consumed by the
+ QmlCompiler. During the compilation phase the compiler will update some of
+ the fields for both its own use and for the use of the upcoming QmlDom API.
+
+ The types are part of the generic sounding "QmlParser" namespace for legacy
+ reasons (there used to be more in this namespace) and will be cleaned up and
+ migrated into a more appropriate location shortly.
+*/
+namespace QmlParser
+{
+ struct Location
+ {
+ Location() : line(-1), column(-1) {}
+ int line;
+ int column;
+ };
+
+ struct LocationRange
+ {
+ LocationRange() : offset(0), length(0) {}
+ quint32 offset;
+ quint32 length;
+ };
+
+ struct LocationSpan
+ {
+ Location start;
+ Location end;
+ LocationRange range;
+ };
+
+ class Property;
+ class Object : public QmlRefCount
+ {
+ public:
+ Object();
+ virtual ~Object();
+
+ // Type of the object. The integer is an index into the
+ // QmlCompiledData::types array, or -1 if the object is a fetched
+ // object.
+ int type;
+ // The name of this type
+ QByteArray typeName;
+ // The id assigned to the object (if any).
+ QByteArray id;
+ // Custom parsed data
+ QByteArray custom;
+ // Returns the metaobject for this type, or 0 if not available.
+ // Internally selectd between the metatype and extObject variables
+ const QMetaObject *metaObject() const;
+
+ // The compile time metaobject for this type
+ const QMetaObject *metatype;
+ // The synthesized metaobject, if QML added signals or properties to
+ // this type. Otherwise null
+ QMetaObject *extObjectData;
+ QAbstractDynamicMetaObject extObject;
+
+ Property *getDefaultProperty();
+ Property *getProperty(const QByteArray &name, bool create=true);
+
+ Property *defaultProperty;
+ QHash<QByteArray, Property *> properties;
+
+ LocationSpan location;
+
+ struct DynamicProperty {
+ DynamicProperty();
+ DynamicProperty(const DynamicProperty &);
+
+ enum Type { Variant, Int, Bool, Real, String, Color, Date };
+
+ bool isDefaultProperty;
+ Type type;
+ QByteArray name;
+ QString onValueChanged;
+ QmlParser::Property *defaultValue;
+ };
+ struct DynamicSignal {
+ DynamicSignal();
+ DynamicSignal(const DynamicSignal &);
+
+ QByteArray name;
+ };
+ struct DynamicSlot {
+ DynamicSlot();
+ DynamicSlot(const DynamicSlot &);
+
+ QByteArray name;
+ QString body;
+ };
+
+ // The list of dynamic properties
+ QList<DynamicProperty> dynamicProperties;
+ // The list of dynamic signals
+ QList<DynamicSignal> dynamicSignals;
+ // The list of dynamic slots
+ QList<DynamicSlot> dynamicSlots;
+
+ void dump(int = 0) const;
+ };
+
+ class Variant
+ {
+ public:
+ enum Type {
+ Invalid,
+ Boolean,
+ Number,
+ String,
+ Script
+ };
+
+ Variant();
+ Variant(const Variant &);
+ Variant(bool);
+ Variant(double);
+ Variant(const QString &, Type = String);
+ Variant &operator=(const Variant &);
+
+ Type type() const;
+
+ bool isBoolean() const { return type() == Boolean; }
+ bool isNumber() const { return type() == Number; }
+ bool isString() const { return type() == String; }
+ bool isScript() const { return type() == Script; }
+
+ bool asBoolean() const;
+ QString asString() const;
+ double asNumber() const;
+ QString asScript() const;
+
+ private:
+ Type t;
+ union {
+ bool b;
+ double d;
+ };
+ QString s;
+ };
+
+ class Value : public QmlRefCount
+ {
+ public:
+ Value();
+ virtual ~Value();
+
+ enum Type {
+ // The type of this value assignment is not yet known
+ Unknown,
+ // This is used as a literal property assignment
+ Literal,
+ // This is used as a property binding assignment
+ PropertyBinding,
+ // This is used as a QmlPropertyValueSource assignment
+ ValueSource,
+ // This is used as a property QObject assignment
+ CreatedObject,
+ // This is used as a signal object assignment
+ SignalObject,
+ // This is used as a signal expression assignment
+ SignalExpression,
+ // This is used as an implicit component creation
+ Component,
+ // This is used as an id assignment only
+ Id
+ };
+ Type type;
+
+ // ### Temporary
+ QString primitive() const { return value.asScript(); }
+
+ // Primitive value
+ Variant value;
+ // Object value
+ Object *object;
+
+ LocationSpan location;
+
+ void dump(int = 0) const;
+ };
+
+ class Property : public QmlRefCount
+ {
+ public:
+ Property();
+ Property(const QByteArray &n);
+ virtual ~Property();
+
+ Object *getValue();
+ void addValue(Value *v);
+
+ // The QVariant::Type of the property, or 0 (QVariant::Invalid) if
+ // unknown.
+ int type;
+ // The metaobject index of this property, or -1 if unknown.
+ int index;
+
+ // The list of values assigned to this property. Content in values
+ // and value are mutually exclusive
+ QList<Value *> values;
+ // The accessed property. This is used to represent dot properties.
+ // Content in value and values are mutually exclusive.
+ Object *value;
+ // The property name
+ QByteArray name;
+ // True if this property was accessed as the default property.
+ bool isDefault;
+
+ LocationSpan location;
+
+ void dump(int = 0) const;
+ };
+}
+
+#endif // QMLPARSER_P_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/qml/qmlparserstatus.cpp b/src/declarative/qml/qmlparserstatus.cpp
new file mode 100644
index 0000000..fceac05
--- /dev/null
+++ b/src/declarative/qml/qmlparserstatus.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlparserstatus.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlParserStatus
+ \brief The QmlParserStatus class provides updates on the parser state.
+*/
+
+/*! \internal */
+QmlParserStatus::QmlParserStatus()
+: d(0)
+{
+}
+
+/*! \internal */
+QmlParserStatus::~QmlParserStatus()
+{
+ if(d)
+ (*d) = 0;
+}
+
+/*!
+ Invoked after class creation, but before any properties have been set.
+*/
+void QmlParserStatus::classBegin()
+{
+}
+
+/*!
+ Invoked after all properties have been set to their static values. At this
+ point bindings are still to be evaluated.
+*/
+void QmlParserStatus::classComplete()
+{
+}
+
+/*!
+ Invoked after the root component that caused this instantiation has
+ completed construction. At this point all static values and binding values
+ have been assigned to the class.
+*/
+void QmlParserStatus::componentComplete()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlparserstatus.h b/src/declarative/qml/qmlparserstatus.h
new file mode 100644
index 0000000..0e58229
--- /dev/null
+++ b/src/declarative/qml/qmlparserstatus.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPARSERSTATUS_H
+#define QMLPARSERSTATUS_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlParserStatus
+{
+public:
+ QmlParserStatus();
+ virtual ~QmlParserStatus();
+
+ virtual void classBegin();
+ virtual void classComplete();
+ virtual void componentComplete();
+
+private:
+ friend class QmlVME;
+ friend class QmlComponent;
+ friend class QmlEnginePrivate;
+ QmlParserStatus **d;
+};
+Q_DECLARE_INTERFACE(QmlParserStatus, "com.trolltech.qml.QmlParserStatus");
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPARSERSTATUS_H
diff --git a/src/declarative/qml/qmlprivate.cpp b/src/declarative/qml/qmlprivate.cpp
new file mode 100644
index 0000000..21b19e8
--- /dev/null
+++ b/src/declarative/qml/qmlprivate.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlprivate.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlPrivate::InstanceType::InstanceType(int) {}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlprivate.h b/src/declarative/qml/qmlprivate.h
new file mode 100644
index 0000000..590e0c0
--- /dev/null
+++ b/src/declarative/qml/qmlprivate.h
@@ -0,0 +1,365 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPRIVATE_H
+#define QMLPRIVATE_H
+
+#include <QtCore/qglobal.h>
+#ifndef Q_OS_WIN32
+#include <stdint.h>
+#endif
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+typedef QObject *(*QmlAttachedPropertiesFunc)(QObject *);
+
+namespace QmlPrivate
+{
+ class ListInterface
+ {
+ public:
+ virtual ~ListInterface() {}
+ virtual int type() const = 0;
+ virtual void append(void *) = 0;
+ virtual void insert(int, void *) = 0;
+ virtual void removeAt(int) = 0;
+ virtual void at(int, void *) const = 0;
+ virtual int count() const = 0;
+ virtual void clear() = 0;
+ };
+
+ enum ListOp { Append, Set, Insert, Prepend, Length, FromObject,
+ Object, Create, Value, Clear };
+
+ template<typename T>
+ int list_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<typename T>
+ int list_nocreate_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<typename T>
+ int list_interface_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<class From, class To, int N>
+ struct StaticCastSelectorClass
+ {
+ static inline int cast() { return -1; }
+ };
+
+ template<class From, class To>
+ struct StaticCastSelectorClass<From, To, sizeof(int)>
+ {
+#ifndef Q_OS_SYMBIAN
+ static inline int cast() { return (int)((intptr_t)static_cast<To *>((From *)0x10000000)) - 0x10000000; }
+#else
+ static inline int cast() { return (int)(static_cast<To *>((From *)0x10000000)) - 0x10000000; }
+#endif
+ };
+
+ template<class From, class To>
+ struct StaticCastSelector
+ {
+ typedef int yes_type;
+ typedef char no_type;
+
+ static yes_type check(To *);
+ static no_type check(...);
+
+ static inline int cast()
+ {
+ return StaticCastSelectorClass<From, To, sizeof(check((From *)0))>::cast();
+ }
+ };
+
+ template<typename T, int N>
+ struct AttachedPropertySelector
+ {
+ static inline QmlAttachedPropertiesFunc func()
+ {
+ return 0;
+ }
+ };
+ template<typename T>
+ struct AttachedPropertySelector<T, 1>
+ {
+ static inline QmlAttachedPropertiesFunc func()
+ {
+ return &T::qmlAttachedProperties;
+ }
+ };
+
+ template < typename T >
+ class has_attachedProperties {
+ typedef int yes_type;
+ typedef char no_type;
+
+ template<typename S, QObject *(S::*)(QObject *)>
+ struct dummy {};
+
+ template<typename S, QObject *(S::*)(QObject *) const>
+ struct dummy_const {};
+
+ template<typename S, QObject *(*) (QObject *)>
+ struct dummy_static {};
+
+ template<typename S>
+ static no_type check(dummy<S, &S::qmlAttachedProperties> *);
+
+ template<typename S>
+ static no_type check(dummy_const<S, &S::qmlAttachedProperties> *);
+
+ template<typename S>
+ static yes_type check(dummy_static<S, &S::qmlAttachedProperties> *);
+
+ template<typename S>
+ static no_type check(...);
+
+ public:
+ static bool const value = sizeof(check<T>(0)) == sizeof(yes_type);
+ };
+
+ template<typename T>
+ inline QmlAttachedPropertiesFunc attachedPropertiesFunc()
+ {
+ return AttachedPropertySelector<T, has_attachedProperties<T>::value>::func();
+ }
+
+ struct MetaTypeIds {
+ int typeId;
+ int listId;
+ int qmlListId;
+ };
+ typedef int (*Func)(QmlPrivate::ListOp, int, const QVariant &, const QVariant &, void **);
+ typedef QObject *(*CreateFunc)(QObject *);
+
+ template<typename T>
+ struct CreateParent {
+ static QObject *create(QObject *other) {
+ return new T(other);
+ }
+ };
+
+ template<typename T>
+ struct CreateNoParent {
+ static QObject *create() {
+ return new T;
+ }
+ };
+
+ struct Q_DECLARATIVE_EXPORT InstanceType {
+ InstanceType(int);
+ };
+
+ template<typename T>
+ struct Define {
+ static InstanceType instance;
+ };
+
+ template<typename T>
+ struct ExtCreate {
+ static QObject *create(QObject *other) {
+ return new T(other);
+ }
+ };
+};
+
+template<typename T>
+int QmlPrivate::list_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ if (op == QmlPrivate::Create) {
+ QObject *obj = static_cast<QObject *>(new T);
+ *((QObject **)out) = obj;
+ return 0;
+ }
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ *out = static_cast<QObject *>(value.value<T *>());
+ break;
+ case QmlPrivate::FromObject:
+ {
+ QObject *fromObj = value.value<QObject *>();
+ T *me = qobject_cast<T *>(fromObj);
+ if (me) {
+ *((QVariant *)*out) = QVariant::fromValue(me);
+ }
+ }
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+template<typename T>
+int QmlPrivate::list_nocreate_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ *out = static_cast<QObject *>(value.value<T *>());
+ break;
+ case QmlPrivate::FromObject:
+ {
+ QObject *fromObj = value.value<QObject *>();
+ T *me = qobject_cast<T *>(fromObj);
+ if (me) {
+ *((QVariant *)*out) = QVariant::fromValue(me);
+ }
+ }
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+template<typename T>
+int QmlPrivate::list_interface_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ break;
+ case QmlPrivate::FromObject:
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+
+#endif // QMLPRIVATE_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/qml/qmlpropertyvaluesource.cpp b/src/declarative/qml/qmlpropertyvaluesource.cpp
new file mode 100644
index 0000000..4770929
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvaluesource.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpropertyvaluesource.h"
+#include "qml.h"
+
+
+QT_BEGIN_NAMESPACE
+/*!
+ \class QmlPropertyValueSource
+ \brief The QmlPropertyValueSource class is inherited by property value sources such as animations and bindings.
+ */
+QML_DEFINE_NOCREATE_TYPE(QmlPropertyValueSource);
+
+/*!
+ Constructs a QmlPropertyValueSource with parent \a parent.
+*/
+QmlPropertyValueSource::QmlPropertyValueSource(QObject *parent)
+ : QObject(parent)
+
+{
+}
+
+/*!
+ \internal
+ */
+QmlPropertyValueSource::QmlPropertyValueSource(QObjectPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ Set the target \a property for the value source. This method will
+ be called by the QML engine when assigning a value source.
+
+ The default implementation does nothing.
+*/
+void QmlPropertyValueSource::setTarget(const QmlMetaProperty &property)
+{
+ Q_UNUSED(property);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertyvaluesource.h b/src/declarative/qml/qmlpropertyvaluesource.h
new file mode 100644
index 0000000..6ef2e38
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvaluesource.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROPERTYVALUESOURCE_H
+#define QMLPROPERTYVALUESOURCE_H
+
+#include <qfxglobal.h>
+#include <qml.h>
+#include <QObject>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QObjectPrivate;
+class QmlMetaProperty;
+class Q_DECLARATIVE_EXPORT QmlPropertyValueSource : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QObject)
+
+public:
+ QmlPropertyValueSource(QObject *parent);
+ virtual void setTarget(const QmlMetaProperty &);
+
+protected:
+ QmlPropertyValueSource(QObjectPrivate &dd, QObject *parent);
+
+private:
+ Q_DISABLE_COPY(QmlPropertyValueSource)
+};
+QML_DECLARE_TYPE(QmlPropertyValueSource);
+
+#endif // QMLPROPERTYVALUESOURCE_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/qml/qmlproxymetaobject.cpp b/src/declarative/qml/qmlproxymetaobject.cpp
new file mode 100644
index 0000000..d24c5c4
--- /dev/null
+++ b/src/declarative/qml/qmlproxymetaobject.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlproxymetaobject_p.h"
+
+
+QT_BEGIN_NAMESPACE
+QmlProxyMetaObject::QmlProxyMetaObject(QObject *obj, QList<ProxyData> *mList)
+: metaObjects(mList), proxies(0), parent(0), object(obj)
+{
+#ifdef QMLPROXYMETAOBJECT_DEBUG
+ qWarning() << "QmlProxyMetaObject" << obj->metaObject()->className();
+#endif
+
+ *static_cast<QMetaObject *>(this) = *metaObjects->last().metaObject;
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ if (op->metaObject)
+ parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject);
+
+ op->metaObject = this;
+
+#ifdef QMLPROXYMETAOBJECT_DEBUG
+ const QMetaObject *mo = obj->metaObject();
+ while(mo) {
+ qWarning() << " " << mo->className();
+ mo = mo->superClass();
+ }
+#endif
+}
+
+QmlProxyMetaObject::~QmlProxyMetaObject()
+{
+ if (parent)
+ delete parent;
+ parent = 0;
+
+ if (proxies)
+ delete [] proxies;
+ proxies = 0;
+}
+
+int QmlProxyMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if ((c == QMetaObject::ReadProperty ||
+ c == QMetaObject::WriteProperty) &&
+ id >= metaObjects->last().propertyOffset) {
+
+ for (int ii = 0; ii < metaObjects->count(); ++ii) {
+ const ProxyData &data = metaObjects->at(ii);
+ if (id >= data.propertyOffset) {
+ if (!proxies) {
+ proxies = new QObject*[metaObjects->count()];
+ ::memset(proxies, 0,
+ sizeof(QObject *) * metaObjects->count());
+ }
+
+ if (!proxies[ii])
+ proxies[ii] = data.createFunc(object);
+
+ int proxyOffset = proxies[ii]->metaObject()->propertyOffset();
+ int proxyId = id - data.propertyOffset + proxyOffset;
+
+ return proxies[ii]->qt_metacall(c, proxyId, a);
+ }
+ }
+ }
+
+ if (parent)
+ return parent->metaCall(c, id, a);
+ else
+ return object->qt_metacall(c, id, a);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlproxymetaobject_p.h b/src/declarative/qml/qmlproxymetaobject_p.h
new file mode 100644
index 0000000..594e7a3
--- /dev/null
+++ b/src/declarative/qml/qmlproxymetaobject_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROXYMETAOBJECT_P_H
+#define QMLPROXYMETAOBJECT_P_H
+
+#include <QMetaObject>
+#include <private/qmetaobjectbuilder_p.h>
+#include <private/qobject_p.h>
+#include <QObject>
+#include <qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlProxyMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ struct ProxyData {
+ typedef QObject *(*CreateFunc)(QObject *);
+ QMetaObject *metaObject;
+ CreateFunc createFunc;
+ int propertyOffset;
+ };
+
+ QmlProxyMetaObject(QObject *, QList<ProxyData> *);
+ virtual ~QmlProxyMetaObject();
+
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+
+private:
+ QList<ProxyData> *metaObjects;
+ QObject **proxies;
+
+ QAbstractDynamicMetaObject *parent;
+ QObject *object;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPROXYMETAOBJECT_P_H
+
diff --git a/src/declarative/qml/qmlrefcount.cpp b/src/declarative/qml/qmlrefcount.cpp
new file mode 100644
index 0000000..8f71f1b
--- /dev/null
+++ b/src/declarative/qml/qmlrefcount.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlrefcount_p.h"
+
+QmlRefCount::QmlRefCount()
+: refCount(1)
+{
+}
+
+QmlRefCount::~QmlRefCount()
+{
+}
+
+void QmlRefCount::addref()
+{
+ Q_ASSERT(refCount > 0);
+ ++refCount;
+}
+
+void QmlRefCount::release()
+{
+ Q_ASSERT(refCount > 0);
+ --refCount;
+ if (refCount == 0)
+ delete this;
+}
+
diff --git a/src/declarative/qml/qmlrefcount_p.h b/src/declarative/qml/qmlrefcount_p.h
new file mode 100644
index 0000000..90b50a8
--- /dev/null
+++ b/src/declarative/qml/qmlrefcount_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLREFCOUNT_P_H
+#define QMLREFCOUNT_P_H
+
+#include <qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlRefCount
+{
+public:
+ QmlRefCount();
+ virtual ~QmlRefCount();
+ void addref();
+ void release();
+
+private:
+ int refCount;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLREFCOUNT_P_H
diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp
new file mode 100644
index 0000000..ae4e903
--- /dev/null
+++ b/src/declarative/qml/qmlscriptparser.cpp
@@ -0,0 +1,736 @@
+
+#include "qmlscriptparser_p.h"
+#include "qmlparser_p.h"
+
+#include "parser/javascriptengine_p.h"
+#include "parser/javascriptparser_p.h"
+#include "parser/javascriptlexer_p.h"
+#include "parser/javascriptnodepool_p.h"
+#include "parser/javascriptastvisitor_p.h"
+#include "parser/javascriptast_p.h"
+
+#include <QStack>
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+using namespace JavaScript;
+using namespace QmlParser;
+
+namespace {
+
+class ProcessAST: protected AST::Visitor
+{
+ struct State {
+ State() : object(0), property(0) {}
+ State(Object *o) : object(o), property(0) {}
+ State(Object *o, Property *p) : object(o), property(p) {}
+
+ Object *object;
+ Property *property;
+ };
+
+ struct StateStack : public QStack<State>
+ {
+ void pushObject(Object *obj)
+ {
+ push(State(obj));
+ }
+
+ void pushProperty(const QString &name, const LocationSpan &location)
+ {
+ const State &state = top();
+ if (state.property) {
+ State s(state.property->getValue(),
+ state.property->getValue()->getProperty(name.toLatin1()));
+ s.property->location = location;
+ push(s);
+ } else {
+ State s(state.object,
+ state.object->getProperty(name.toLatin1()));
+
+ s.property->location = location;
+ push(s);
+ }
+ }
+ };
+
+public:
+ ProcessAST(QmlScriptParser *parser);
+ virtual ~ProcessAST();
+
+ void operator()(const QString &code, AST::Node *node);
+
+protected:
+ Object *defineObjectBinding(int line,
+ AST::UiQualifiedId *propertyName,
+ const QString &objectType,
+ AST::SourceLocation typeLocation,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer = 0);
+ Object *defineObjectBinding_helper(int line,
+ AST::UiQualifiedId *propertyName,
+ const QString &objectType,
+ AST::SourceLocation typeLocation,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer = 0);
+
+ QmlParser::Variant getVariant(AST::ExpressionNode *expr);
+
+ LocationSpan location(AST::SourceLocation start, AST::SourceLocation end);
+ LocationSpan location(AST::UiQualifiedId *);
+
+ using AST::Visitor::visit;
+ using AST::Visitor::endVisit;
+
+ virtual bool visit(AST::UiProgram *node);
+ virtual bool visit(AST::UiImport *node);
+ virtual bool visit(AST::UiObjectDefinition *node);
+ virtual bool visit(AST::UiPublicMember *node);
+ virtual bool visit(AST::UiObjectBinding *node);
+
+ virtual bool visit(AST::UiScriptBinding *node);
+ virtual bool visit(AST::UiArrayBinding *node);
+ virtual bool visit(AST::UiSourceElement *node);
+
+ void accept(AST::Node *node);
+
+ QString asString(AST::UiQualifiedId *node) const;
+
+ const State state() const;
+ Object *currentObject() const;
+ Property *currentProperty() const;
+
+ QString qualifiedNameId() const;
+
+ QString textAt(const AST::SourceLocation &loc) const
+ { return _contents.mid(loc.offset, loc.length); }
+
+ QString textAt(const AST::SourceLocation &first,
+ const AST::SourceLocation &last) const
+ { return _contents.mid(first.offset, last.offset + last.length - first.offset); }
+
+ QString asString(AST::ExpressionNode *expr) const
+ {
+ if (! expr)
+ return QString();
+
+ return textAt(expr->firstSourceLocation(), expr->lastSourceLocation());
+ }
+
+ QString asString(AST::Statement *stmt) const
+ {
+ if (! stmt)
+ return QString();
+
+ QString s = textAt(stmt->firstSourceLocation(), stmt->lastSourceLocation());
+ s += QLatin1Char('\n');
+ return s;
+ }
+
+private:
+ QmlScriptParser *_parser;
+ StateStack _stateStack;
+ QStringList _scope;
+ QString _contents;
+
+ inline bool isSignalProperty(const QByteArray &propertyName) const {
+ return (propertyName.length() >= 3 && propertyName.startsWith("on") &&
+ ('A' <= propertyName.at(2) && 'Z' >= propertyName.at(2)));
+ }
+
+};
+
+ProcessAST::ProcessAST(QmlScriptParser *parser)
+ : _parser(parser)
+{
+}
+
+ProcessAST::~ProcessAST()
+{
+}
+
+void ProcessAST::operator()(const QString &code, AST::Node *node)
+{
+ _contents = code;
+ accept(node);
+}
+
+void ProcessAST::accept(AST::Node *node)
+{
+ AST::Node::acceptChild(node, this);
+}
+
+const ProcessAST::State ProcessAST::state() const
+{
+ if (_stateStack.isEmpty())
+ return State();
+
+ return _stateStack.back();
+}
+
+Object *ProcessAST::currentObject() const
+{
+ return state().object;
+}
+
+Property *ProcessAST::currentProperty() const
+{
+ return state().property;
+}
+
+QString ProcessAST::qualifiedNameId() const
+{
+ return _scope.join(QLatin1String("/"));
+}
+
+QString ProcessAST::asString(AST::UiQualifiedId *node) const
+{
+ QString s;
+
+ for (AST::UiQualifiedId *it = node; it; it = it->next) {
+ s.append(it->name->asString());
+
+ if (it->next)
+ s.append(QLatin1Char('.'));
+ }
+
+ return s;
+}
+
+Object *
+ProcessAST::defineObjectBinding_helper(int line,
+ AST::UiQualifiedId *propertyName,
+ const QString &objectType,
+ AST::SourceLocation typeLocation,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer)
+{
+ bool isType = !objectType.isEmpty() && objectType.at(0).isUpper() && !objectType.contains(QLatin1Char('.'));
+
+ int propertyCount = 0;
+ for (; propertyName; propertyName = propertyName->next){
+ ++propertyCount;
+ _stateStack.pushProperty(propertyName->name->asString(),
+ this->location(propertyName));
+ }
+
+ if (!isType) {
+
+ if(propertyCount || !currentObject()) {
+ QmlError error;
+ error.setDescription("Expected type name");
+ error.setLine(typeLocation.startLine);
+ error.setColumn(typeLocation.startColumn);
+ _parser->_errors << error;
+ return 0;
+ }
+
+ LocationSpan loc = ProcessAST::location(typeLocation, typeLocation);
+ if (propertyName)
+ loc = ProcessAST::location(propertyName);
+
+ _stateStack.pushProperty(objectType, loc);
+ accept(initializer);
+ _stateStack.pop();
+
+ return 0;
+
+ } else {
+
+ // Class
+ const int typeId = _parser->findOrCreateTypeId(objectType);
+
+ Object *obj = new Object;
+ obj->type = typeId;
+ _scope.append(objectType);
+ obj->typeName = qualifiedNameId().toLatin1();
+ _scope.removeLast();
+ obj->location = location;
+
+ if (propertyCount) {
+
+ Property *prop = currentProperty();
+ Value *v = new Value;
+ v->object = obj;
+ v->location = obj->location;
+ prop->addValue(v);
+
+ while (propertyCount--)
+ _stateStack.pop();
+
+ } else {
+
+ if (! _parser->tree()) {
+ _parser->setTree(obj);
+ } else {
+ const State state = _stateStack.top();
+ Value *v = new Value;
+ v->object = obj;
+ v->location = obj->location;
+ if (state.property)
+ state.property->addValue(v);
+ else
+ state.object->getDefaultProperty()->addValue(v);
+ }
+ }
+
+ _stateStack.pushObject(obj);
+ accept(initializer);
+ _stateStack.pop();
+
+ return obj;
+ }
+}
+
+Object *ProcessAST::defineObjectBinding(int line,
+ AST::UiQualifiedId *qualifiedId,
+ const QString &objectType,
+ AST::SourceLocation typeLocation,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer)
+{
+ if (objectType == QLatin1String("Connection")) {
+
+ Object *obj = defineObjectBinding_helper(line, 0, objectType, typeLocation, location);
+
+ _stateStack.pushObject(obj);
+
+ AST::UiObjectMemberList *it = initializer->members;
+ for (; it; it = it->next) {
+ AST::UiScriptBinding *scriptBinding = AST::cast<AST::UiScriptBinding *>(it->member);
+ if (! scriptBinding)
+ continue;
+
+ QString propertyName = asString(scriptBinding->qualifiedId);
+ if (propertyName == QLatin1String("script")) {
+ QString script;
+
+ if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(scriptBinding->statement)) {
+ script = getVariant(stmt->expression).asScript();
+ } else {
+ script = asString(scriptBinding->statement);
+ }
+
+ LocationSpan l = this->location(scriptBinding->statement->firstSourceLocation(),
+ scriptBinding->statement->lastSourceLocation());
+
+ _stateStack.pushProperty(QLatin1String("script"), l);
+ Value *value = new Value;
+ value->value = QmlParser::Variant(script);
+ value->location = l;
+ currentProperty()->addValue(value);
+ _stateStack.pop();
+ } else {
+ accept(it->member);
+ }
+ }
+
+ _stateStack.pop(); // object
+
+ return obj;
+ }
+
+ return defineObjectBinding_helper(line, qualifiedId, objectType, typeLocation, location, initializer);
+}
+
+LocationSpan ProcessAST::location(AST::UiQualifiedId *id)
+{
+ return location(id->identifierToken, id->identifierToken);
+}
+
+LocationSpan ProcessAST::location(AST::SourceLocation start, AST::SourceLocation end)
+{
+ LocationSpan rv;
+ rv.start.line = start.startLine;
+ rv.start.column = start.startColumn;
+ rv.end.line = end.startLine;
+ rv.end.column = end.startColumn + end.length - 1;
+ rv.range.offset = start.offset;
+ rv.range.length = end.offset + end.length - start.offset;
+ return rv;
+}
+
+// UiProgram: UiImportListOpt UiObjectMemberList ;
+bool ProcessAST::visit(AST::UiProgram *node)
+{
+ accept(node->imports);
+ accept(node->members->member);
+ return false;
+}
+
+// UiImport: T_IMPORT T_STRING_LITERAL ;
+bool ProcessAST::visit(AST::UiImport *node)
+{
+ QString fileName = node->fileName->asString();
+ _parser->addNamespacePath(fileName);
+
+ AST::SourceLocation startLoc = node->importToken;
+ AST::SourceLocation endLoc = node->semicolonToken;
+
+ QmlScriptParser::Import import;
+ import.location = location(startLoc, endLoc);
+ import.uri = fileName;
+
+ _parser->_imports << import;
+
+ return false;
+}
+
+bool ProcessAST::visit(AST::UiPublicMember *node)
+{
+ if(node->type == AST::UiPublicMember::Signal) {
+ const QString name = node->name->asString();
+
+ Object::DynamicSignal signal;
+ signal.name = name.toUtf8();
+
+ _stateStack.top().object->dynamicSignals << signal;
+ } else {
+ const QString memberType = node->memberType->asString();
+ const QString name = node->name->asString();
+
+ const struct TypeNameToType {
+ const char *name;
+ Object::DynamicProperty::Type type;
+ } propTypeNameToTypes[] = {
+ { "int", Object::DynamicProperty::Int },
+ { "bool", Object::DynamicProperty::Bool },
+ { "double", Object::DynamicProperty::Real },
+ { "real", Object::DynamicProperty::Real },
+ { "string", Object::DynamicProperty::String },
+ { "color", Object::DynamicProperty::Color },
+ { "date", Object::DynamicProperty::Date },
+ { "var", Object::DynamicProperty::Variant },
+ { "variant", Object::DynamicProperty::Variant }
+ };
+ const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) /
+ sizeof(propTypeNameToTypes[0]);
+
+ bool typeFound = false;
+ Object::DynamicProperty::Type type;
+ for(int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
+ if(QLatin1String(propTypeNameToTypes[ii].name) == memberType) {
+ type = propTypeNameToTypes[ii].type;
+ typeFound = true;
+ }
+ }
+
+ if(!typeFound) {
+ QmlError error;
+ error.setDescription("Expected property type");
+ error.setLine(node->typeToken.startLine);
+ error.setColumn(node->typeToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ Object::DynamicProperty property;
+ property.isDefaultProperty = node->isDefaultMember;
+ property.type = type;
+ property.name = name.toUtf8();
+
+ if (node->expression) { // default value
+ property.defaultValue = new Property;
+ Value *value = new Value;
+ value->location = location(node->expression->firstSourceLocation(),
+ node->expression->lastSourceLocation());
+ value->value = getVariant(node->expression);
+ property.defaultValue->values << value;
+ }
+
+ _stateStack.top().object->dynamicProperties << property;
+ }
+
+ return true;
+}
+
+
+// UiObjectMember: T_IDENTIFIER UiObjectInitializer ;
+bool ProcessAST::visit(AST::UiObjectDefinition *node)
+{
+ LocationSpan l = location(node->firstSourceLocation(),
+ node->lastSourceLocation());;
+
+ defineObjectBinding(node->identifierToken.startLine,
+ 0,
+ node->name->asString(),
+ node->identifierToken,
+ l,
+ node->initializer);
+
+ return false;
+}
+
+
+// UiObjectMember: UiQualifiedId T_COLON T_IDENTIFIER UiObjectInitializer ;
+bool ProcessAST::visit(AST::UiObjectBinding *node)
+{
+ LocationSpan l;
+ l = location(node->identifierToken, node->initializer->rbraceToken);
+
+ defineObjectBinding(node->identifierToken.startLine,
+ node->qualifiedId,
+ node->name->asString(),
+ node->identifierToken,
+ l,
+ node->initializer);
+
+ return false;
+}
+
+QmlParser::Variant ProcessAST::getVariant(AST::ExpressionNode *expr)
+{
+ if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(expr)) {
+ return QmlParser::Variant(lit->value->asString());
+ } else if (expr->kind == AST::Node::Kind_TrueLiteral) {
+ return QmlParser::Variant(true);
+ } else if (expr->kind == AST::Node::Kind_FalseLiteral) {
+ return QmlParser::Variant(false);
+ } else if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(expr)) {
+ return QmlParser::Variant(lit->value);
+ } else {
+
+ if (AST::UnaryMinusExpression *unaryMinus = AST::cast<AST::UnaryMinusExpression *>(expr)) {
+ if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(unaryMinus->expression)) {
+ return QmlParser::Variant(-lit->value);
+ }
+ }
+
+ return QmlParser::Variant(asString(expr), QmlParser::Variant::Script);
+ }
+}
+
+
+// UiObjectMember: UiQualifiedId T_COLON Statement ;
+bool ProcessAST::visit(AST::UiScriptBinding *node)
+{
+ int propertyCount = 0;
+ AST::UiQualifiedId *propertyName = node->qualifiedId;
+ for (; propertyName; propertyName = propertyName->next){
+ ++propertyCount;
+ _stateStack.pushProperty(propertyName->name->asString(),
+ location(propertyName));
+ }
+
+ Property *prop = currentProperty();
+
+ QmlParser::Variant primitive;
+
+ if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(node->statement)) {
+ primitive = getVariant(stmt->expression);
+ } else { // do binding
+ primitive = QmlParser::Variant(asString(node->statement),
+ QmlParser::Variant::Script);
+ }
+
+ Value *v = new Value;
+ v->value = primitive;
+ v->location = location(node->statement->firstSourceLocation(),
+ node->statement->lastSourceLocation());
+
+ prop->addValue(v);
+
+ while (propertyCount--)
+ _stateStack.pop();
+
+ return true;
+}
+
+// UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiObjectMemberList T_RBRACKET ;
+bool ProcessAST::visit(AST::UiArrayBinding *node)
+{
+ int propertyCount = 0;
+ AST::UiQualifiedId *propertyName = node->qualifiedId;
+ for (; propertyName; propertyName = propertyName->next){
+ ++propertyCount;
+ _stateStack.pushProperty(propertyName->name->asString(),
+ location(propertyName));
+ }
+
+ accept(node->members);
+
+ while (propertyCount--)
+ _stateStack.pop();
+
+ return false;
+}
+
+bool ProcessAST::visit(AST::UiSourceElement *node)
+{
+ QmlParser::Object *obj = currentObject();
+
+ bool isScript = (obj && obj->typeName == "Script");
+
+ if (!isScript) {
+
+ if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) {
+
+ if(funDecl->formals) {
+ QmlError error;
+ error.setDescription("Slot declarations must be parameterless");
+ error.setLine(funDecl->lparenToken.startLine);
+ error.setColumn(funDecl->lparenToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ QString body = textAt(funDecl->lbraceToken, funDecl->rbraceToken);
+ Object::DynamicSlot slot;
+ slot.name = funDecl->name->asString().toUtf8();
+ slot.body = body;
+ obj->dynamicSlots << slot;
+ } else {
+ QmlError error;
+ error.setDescription("JavaScript declaration outside Script element");
+ error.setLine(node->firstSourceLocation().startLine);
+ error.setColumn(node->firstSourceLocation().startColumn);
+ _parser->_errors << error;
+ }
+ return false;
+
+ } else {
+ QString source;
+
+ int line = 0;
+ if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) {
+ line = funDecl->functionToken.startLine;
+ source = asString(funDecl);
+ } else if (AST::VariableStatement *varStmt = AST::cast<AST::VariableStatement *>(node->sourceElement)) {
+ // ignore variable declarations
+ line = varStmt->declarationKindToken.startLine;
+ }
+
+ Value *value = new Value;
+ value->location = location(node->firstSourceLocation(),
+ node->lastSourceLocation());
+ value->value = QmlParser::Variant(source);
+
+ obj->getDefaultProperty()->addValue(value);
+ }
+
+ return false;
+}
+
+} // end of anonymous namespace
+
+
+QmlScriptParser::QmlScriptParser()
+: root(0)
+{
+
+}
+
+QmlScriptParser::~QmlScriptParser()
+{
+}
+
+bool QmlScriptParser::parse(const QByteArray &data, const QUrl &url)
+{
+ const QString fileName = url.toString();
+
+ QTextStream stream(data, QIODevice::ReadOnly);
+ const QString code = stream.readAll();
+
+ JavaScriptParser parser;
+ JavaScriptEnginePrivate driver;
+
+ NodePool nodePool(fileName, &driver);
+ driver.setNodePool(&nodePool);
+
+ Lexer lexer(&driver);
+ lexer.setCode(code, /*line = */ 1);
+ driver.setLexer(&lexer);
+
+ if (! parser.parse(&driver) || !_errors.isEmpty()) {
+
+ // Extract errors from the parser
+ foreach (const JavaScriptParser::DiagnosticMessage &m, parser.diagnosticMessages()) {
+
+ if (m.isWarning())
+ continue;
+
+ QmlError error;
+ error.setUrl(url);
+ error.setDescription(m.message);
+ error.setLine(m.loc.startLine);
+ error.setColumn(m.loc.startColumn);
+ _errors << error;
+
+ }
+ }
+
+ if (_errors.isEmpty()) {
+ ProcessAST process(this);
+ process(code, parser.ast());
+
+ // Set the url for process errors
+ for(int ii = 0; ii < _errors.count(); ++ii)
+ _errors[ii].setUrl(url);
+ }
+
+ return _errors.isEmpty();
+}
+
+QMap<QString,QString> QmlScriptParser::nameSpacePaths() const
+{
+ return _nameSpacePaths;
+}
+
+QStringList QmlScriptParser::types() const
+{
+ return _typeNames;
+}
+
+Object *QmlScriptParser::tree() const
+{
+ return root;
+}
+
+QList<QmlScriptParser::Import> QmlScriptParser::imports() const
+{
+ return _imports;
+}
+
+QList<QmlError> QmlScriptParser::errors() const
+{
+ return _errors;
+}
+
+void QmlScriptParser::clear()
+{
+ if (root) {
+ root->release();
+ root = 0;
+ }
+ _nameSpacePaths.clear();
+ _typeNames.clear();
+ _errors.clear();
+}
+
+int QmlScriptParser::findOrCreateTypeId(const QString &name)
+{
+ int index = _typeNames.indexOf(name);
+
+ if (index == -1) {
+ index = _typeNames.size();
+ _typeNames.append(name);
+ }
+
+ return index;
+}
+
+void QmlScriptParser::setTree(Object *tree)
+{
+ Q_ASSERT(! root);
+
+ root = tree;
+}
+
+void QmlScriptParser::addNamespacePath(const QString &path)
+{
+ _nameSpacePaths.insertMulti(QString(), path);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlscriptparser_p.h b/src/declarative/qml/qmlscriptparser_p.h
new file mode 100644
index 0000000..8a5466f
--- /dev/null
+++ b/src/declarative/qml/qmlscriptparser_p.h
@@ -0,0 +1,66 @@
+#ifndef QMLSCRIPTPARSER_P_H
+#define QMLSCRIPTPARSER_P_H
+
+#include <QtCore/QList>
+#include <QtCore/QUrl>
+#include <QtDeclarative/qmlerror.h>
+#include "qmlparser_p.h"
+
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QByteArray;
+
+class QmlScriptParser
+{
+public:
+ class Import
+ {
+ public:
+ Import() {}
+
+ QString uri;
+ QmlParser::LocationSpan location;
+ };
+
+ QmlScriptParser();
+ ~QmlScriptParser();
+
+ bool parse(const QByteArray &data, const QUrl &url = QUrl());
+
+ QMap<QString,QString> nameSpacePaths() const;
+ QStringList types() const;
+
+ QmlParser::Object *tree() const;
+ QList<Import> imports() const;
+
+ void clear();
+
+ QList<QmlError> errors() const;
+
+// ### private:
+ int findOrCreateTypeId(const QString &name);
+ void setTree(QmlParser::Object *tree);
+
+ void setScriptFile(const QString &filename) {_scriptFile = filename; }
+ QString scriptFile() const { return _scriptFile; }
+
+ void addNamespacePath(const QString &path);
+
+// ### private:
+ QList<QmlError> _errors;
+
+ QMap<QString,QString> _nameSpacePaths;
+ QmlParser::Object *root;
+ QList<Import> _imports;
+ QStringList _typeNames;
+ QString _scriptFile;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QMLSCRIPTPARSER_P_H
diff --git a/src/declarative/qml/qmlstringconverters.cpp b/src/declarative/qml/qmlstringconverters.cpp
new file mode 100644
index 0000000..c1f4b8c
--- /dev/null
+++ b/src/declarative/qml/qmlstringconverters.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qcolor.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qvariant.h>
+#include "qmlstringconverters_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static uchar fromHex(const uchar c, const uchar c2)
+{
+ uchar rv = 0;
+ if (c >= '0' && c <= '9')
+ rv += (c - '0') * 16;
+ else if (c >= 'A' && c <= 'F')
+ rv += (c - 'A' + 10) * 16;
+ else if (c >= 'a' && c <= 'f')
+ rv += (c - 'a' + 10) * 16;
+
+ if (c2 >= '0' && c2 <= '9')
+ rv += (c2 - '0');
+ else if (c2 >= 'A' && c2 <= 'F')
+ rv += (c2 - 'A' + 10);
+ else if (c2 >= 'a' && c2 <= 'f')
+ rv += (c2 - 'a' + 10);
+
+ return rv;
+}
+
+static uchar fromHex(const QString &s, int idx)
+{
+ uchar c = s.at(idx).toAscii();
+ uchar c2 = s.at(idx + 1).toAscii();
+ return fromHex(c, c2);
+}
+
+QVariant QmlStringConverters::variantFromString(const QString &s)
+{
+ if (s.isEmpty())
+ return QVariant(s);
+ if (s.startsWith(QLatin1Char('\'')) && s.endsWith(QLatin1Char('\''))) {
+ QString data = s.mid(1, s.length() - 2);
+ return QVariant(data);
+ }
+ bool ok = false;
+ QRectF r = rectFFromString(s, &ok);
+ if (ok) return QVariant(r);
+ QColor c = colorFromString(s, &ok);
+ if (ok) return QVariant(c);
+ QPointF p = pointFFromString(s, &ok);
+ if (ok) return QVariant(p);
+ QSizeF sz = sizeFFromString(s, &ok);
+ if (ok) return QVariant(sz);
+ bool b = boolFromString(s, &ok);
+ if (ok) return QVariant(b);
+
+ return QVariant(s);
+}
+
+QColor QmlStringConverters::colorFromString(const QString &s, bool *ok)
+{
+ if (s.startsWith(QLatin1Char('#')) && s.length() == 9) {
+ uchar a = fromHex(s, 1);
+ uchar r = fromHex(s, 3);
+ uchar g = fromHex(s, 5);
+ uchar b = fromHex(s, 7);
+ if (ok) *ok = true;
+ return QColor(r, g, b, a);
+ } else {
+ QColor rv;
+ if (s.startsWith(QLatin1Char('#')) || QColor::colorNames().contains(s.toLower()))
+ rv = QColor(s);
+ if (ok) *ok = rv.isValid();
+ return rv;
+ }
+}
+
+//expects input of "x,y"
+QPointF QmlStringConverters::pointFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 1) {
+ if (ok)
+ *ok = false;
+ return QPointF();
+ }
+
+ bool xGood, yGood;
+ int index = s.indexOf(QLatin1Char(','));
+ qreal xCoord = s.left(index).toDouble(&xGood);
+ qreal yCoord = s.mid(index+1).toDouble(&yGood);
+ if (!xGood || !yGood) {
+ if (ok)
+ *ok = false;
+ return QPointF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QPointF(xCoord, yCoord);
+}
+
+//expects input of "widthxheight"
+QSizeF QmlStringConverters::sizeFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char('x')) != 1) {
+ if (ok)
+ *ok = false;
+ return QSizeF();
+ }
+
+ bool wGood, hGood;
+ int index = s.indexOf(QLatin1Char('x'));
+ qreal width = s.left(index).toDouble(&wGood);
+ qreal height = s.mid(index+1).toDouble(&hGood);
+ if (!wGood || !hGood) {
+ if (ok)
+ *ok = false;
+ return QSizeF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QSizeF(width, height);
+}
+
+//expects input of "x,y,widthxheight" //### use space instead of second comma?
+QRectF QmlStringConverters::rectFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 2 || s.count(QLatin1Char('x')) != 1) {
+ if (ok)
+ *ok = false;
+ return QRectF();
+ }
+
+ bool xGood, yGood, wGood, hGood;
+ int index = s.indexOf(QLatin1Char(','));
+ qreal x = s.left(index).toDouble(&xGood);
+ int index2 = s.indexOf(QLatin1Char(','), index+1);
+ qreal y = s.mid(index+1, index2-index-1).toDouble(&yGood);
+ index = s.indexOf(QLatin1Char('x'), index2+1);
+ qreal width = s.mid(index2+1, index-index2-1).toDouble(&wGood);
+ qreal height = s.mid(index+1).toDouble(&hGood);
+ if (!xGood || !yGood || !wGood || !hGood) {
+ if (ok)
+ *ok = false;
+ return QRectF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QRectF(x, y, width, height);
+}
+
+bool QmlStringConverters::boolFromString(const QString &str, bool *ok)
+{
+ if (str.isEmpty() || str == QLatin1String("false") || str == QLatin1String("0")) {
+ if (ok)
+ *ok = true;
+ return false;
+ } else if (str == QLatin1String("true") || str == QLatin1String("1")) {
+ if (ok)
+ *ok = true;
+ return true;
+ }
+
+ if (ok)
+ *ok = false;
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlstringconverters_p.h b/src/declarative/qml/qmlstringconverters_p.h
new file mode 100644
index 0000000..ed1f959
--- /dev/null
+++ b/src/declarative/qml/qmlstringconverters_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTRINGCONVERTERS_P_H
+#define QMLSTRINGCONVERTERS_P_H
+
+#include <QtCore/qglobal.h>
+class QColor;
+class QPointF;
+class QSizeF;
+class QRectF;
+class QString;
+class QByteArray;
+
+QT_BEGIN_NAMESPACE
+
+// XXX - Bauhaus currently uses these methods which is why they're exported
+namespace QmlStringConverters
+{
+ QVariant Q_DECLARATIVE_EXPORT variantFromString(const QString &);
+ QColor Q_DECLARATIVE_EXPORT colorFromString(const QString &, bool *ok = 0);
+ QPointF Q_DECLARATIVE_EXPORT pointFFromString(const QString &, bool *ok = 0);
+ QSizeF Q_DECLARATIVE_EXPORT sizeFFromString(const QString &, bool *ok = 0);
+ QRectF Q_DECLARATIVE_EXPORT rectFFromString(const QString &, bool *ok = 0);
+ bool Q_DECLARATIVE_EXPORT boolFromString(const QString &, bool *ok = 0);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLSTRINGCONVERTERS_P_H
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
new file mode 100644
index 0000000..240dcc1
--- /dev/null
+++ b/src/declarative/qml/qmlvme.cpp
@@ -0,0 +1,1361 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlvme_p.h"
+#include <qfxperf.h>
+#include <private/qmlboundsignal_p.h>
+#include <private/qmlstringconverters_p.h>
+#include "private/qmetaobjectbuilder_p.h"
+#include <qml.h>
+#include <private/qmlcustomparser_p.h>
+#include <qperformancelog.h>
+#include <QStack>
+#include <QWidget>
+#include <private/qmlcompiledcomponent_p.h>
+#include <QColor>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <qmlengine.h>
+#include <qmlcontext.h>
+#include <qmlcomponent.h>
+#include <qmlbindablevalue.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlcomponent_p.h>
+#include "private/qmlvmemetaobject_p.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qvarlengtharray.h>
+#include <private/qmlbindablevalue_p.h>
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_PERFORMANCE_LOG(QFxCompiler) {
+ Q_DECLARE_PERFORMANCE_METRIC(InstrCreateObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrCreateCustomObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrSetId);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrSetDefault);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrCreateComponent);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreMetaObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreReal);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreInteger);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreBool);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreString);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreColor);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreDate);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreDateTime);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreTime);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStorePoint);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreSize);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreVariant);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreSignal);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObjectQmlList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignConstant);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignSignal);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignSignalObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignBinding);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignCompiledBinding);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignValueSource);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreBinding);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreCompiledBinding);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreValueSource);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrTryBeginObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrBeginObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrTryCompleteObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrCompleteObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignObjectList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrFetchAttached);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrFetchQmlList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrFetchQList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrFetchObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrResolveFetchObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrPopFetchedObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrPopQList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrPushProperty);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignStackObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreStackObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrNoOp);
+ Q_DECLARE_PERFORMANCE_METRIC(Dummy);
+}
+
+Q_DEFINE_PERFORMANCE_LOG(QFxCompiler, "QFxCompiler") {
+ Q_DEFINE_PERFORMANCE_METRIC(InstrCreateObject, "CreateObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrCreateCustomObject, "CreateCustomObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrSetId, "SetId");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrSetDefault, "SetDefault");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrCreateComponent, "CreateComponent");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreMetaObject, "StoreMetaObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreReal, "StoreReal");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreInteger, "StoreInteger");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreBool, "StoreBool");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreString, "StoreString");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreColor, "StoreColor");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreDate, "StoreDate");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreDateTime, "StoreDateTime");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreTime, "StoreTime");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStorePoint, "StorePoint(F)");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreSize, "StoreSize(F)");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreVariant, "StoreVariant");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObject, "StoreObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreSignal, "StoreSignal");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObjectQmlList, "StoreObjectQmlList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignConstant, "AssignConstant");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignSignal, "AssignSignal");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignSignalObject, "AssignSignalObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignBinding, "AssignBinding");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignCompiledBinding, "AssignCompiledBinding");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignValueSource, "AssignValueSource");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreBinding, "StoreBinding");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreCompiledBinding, "StoreCompiledBinding");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreValueSource, "StoreValueSource");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrTryBeginObject, "TryBeginObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrBeginObject, "BeginObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrTryCompleteObject, "TryCompleteObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrCompleteObject, "CompleteObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignObject, "AssignObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignObjectList, "AssignObjectList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrFetchAttached, "FetchAttached");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrFetchQmlList, "FetchQmlList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrFetchQList, "FetchQList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrFetchObject, "FetchObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrResolveFetchObject, "ResolveFetchObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrPopFetchedObject, "PopFetchedObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrPopQList, "PopQList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrPushProperty, "PushProperty");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignStackObject, "AssignStackObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreStackObject, "StoreStackObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrNoOp, "NoOp");
+ Q_DEFINE_PERFORMANCE_METRIC(Dummy, "Dummy");
+}
+
+static inline int qIndexOfProperty(QObject *o, const char *name)
+{
+ int idx = o->metaObject()->indexOfProperty(name);
+ return idx;
+}
+
+QmlVME::QmlVME()
+{
+}
+
+#define VME_EXCEPTION(desc) \
+ { \
+ QString str; \
+ QDebug d(&str); \
+ d << desc; \
+ str = str.trimmed(); \
+ QmlError error; \
+ error.setDescription(str); \
+ error.setLine(instr.line); \
+ error.setUrl(comp->url); \
+ vmeErrors << error; \
+ break; \
+ }
+
+struct ListInstance
+{
+ ListInstance() {}
+ ListInstance(const QVariant &l, int t)
+ : list(l), type(t), qmlListInterface(0) {}
+ ListInstance(QmlPrivate::ListInterface *q, int t)
+ : type(t), qmlListInterface(q) {}
+
+ QVariant list;
+ int type;
+ QmlPrivate::ListInterface *qmlListInterface;
+};
+
+QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, int count)
+{
+ // XXX - All instances of QmlContext::activeContext() here should be
+ // replaced with the use of ctxt. However, this cannot be done until
+ // behaviours stop modifying the active context and expecting the
+ // instantiation to notice. Instead, QmlParserStatus::beginClass() should
+ // be able to return a QmlContext that is used for expressions and
+ // sub-instances on that type.
+ Q_ASSERT(comp);
+ Q_ASSERT(ctxt);
+ const QList<QmlCompiledComponent::TypeReference> &types = comp->types;
+ const QList<QString> &primitives = comp->primitives;
+ const QList<QByteArray> &datas = comp->datas;
+ const QList<QMetaObject *> &synthesizedMetaObjects = comp->synthesizedMetaObjects;;
+ const QList<QmlCompiledData::CustomTypeData> &customTypeData = comp->customTypeData;
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::CompileRun> cr;
+#endif
+ QmlEnginePrivate::SimpleList<QmlBindableValue> bindValues;
+ QmlEnginePrivate::SimpleList<QmlParserStatus> parserStatus;
+
+ QStack<QObject *> stack;
+ QStack<ListInstance> qliststack;
+
+ QStack<QmlMetaProperty> pushedProperties;
+ QObject **savedObjects = 0;
+
+ vmeErrors.clear();
+
+ if (start == -1) start = 0;
+ if (count == -1) count = comp->bytecode.count();
+
+ for (int ii = start; !isError() && ii < (start + count); ++ii) {
+ QmlInstruction &instr = comp->bytecode[ii];
+
+ if (instr.type >= QmlInstruction::StoreInstructionsStart &&
+ instr.type <= QmlInstruction::StoreInstructionsEnd) {
+
+ runStoreInstruction(stack, instr, comp);
+
+ } else {
+
+ switch(instr.type) {
+ case QmlInstruction::Init:
+ {
+ if (instr.init.dataSize) {
+ savedObjects = new QObject*[instr.init.dataSize];
+ ::memset(savedObjects, 0,
+ sizeof(QObject *)*instr.init.dataSize);
+ }
+
+ if (instr.init.bindingsSize)
+ bindValues = QmlEnginePrivate::SimpleList<QmlBindableValue>(instr.init.bindingsSize);
+ if (instr.init.parserStatusSize)
+ parserStatus = QmlEnginePrivate::SimpleList<QmlParserStatus>(instr.init.parserStatusSize);
+ }
+ break;
+
+ case QmlInstruction::CreateObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrCreateObject> cc;
+#endif
+ QObject *o = types.at(instr.create.type).createInstance(QmlContext::activeContext());
+ if (!o) {
+ if(types.at(instr.create.type).component)
+ vmeErrors << types.at(instr.create.type).component->errors();
+
+ VME_EXCEPTION("Unable to create object of type" << types.at(instr.create.type).className);
+ }
+
+ if (instr.create.data != -1) {
+ QmlCustomParser *customParser =
+ types.at(instr.create.type).type->customParser();
+ customParser->setCustomData(o, datas.at(instr.create.data));
+ }
+ if (!stack.isEmpty()) {
+ QObject *parent = stack.top();
+ if (o->isWidgetType()) {
+ qobject_cast<QWidget*>(o)->setParent(qobject_cast<QWidget*>(parent));
+ } else {
+ o->setParent(parent);
+ }
+ }
+ stack.push(o);
+ }
+ break;
+
+ case QmlInstruction::SetId:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrSetId> cc;
+#endif
+ QObject *target = stack.top();
+ QmlContext *ctxt =
+ QmlContext::activeContext();
+ ctxt->setContextProperty(primitives.at(instr.setId.value), target);
+
+ if (instr.setId.save != -1)
+ savedObjects[instr.setId.save] = target;
+ }
+ break;
+
+
+ case QmlInstruction::SetDefault:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrSetDefault> cc;
+#endif
+ QObject *target = stack.top();
+ QmlContext::activeContext()->addDefaultObject(target);
+ }
+ break;
+
+ case QmlInstruction::CreateComponent:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrCreateComponent> cc;
+#endif
+ QObject *qcomp = new QmlComponent(ctxt->engine(), comp, ii + 1, instr.createComponent.count, stack.isEmpty() ? 0 : stack.top());
+ stack.push(qcomp);
+ ii += instr.createComponent.count;
+ }
+ break;
+
+ case QmlInstruction::StoreMetaObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreMetaObject> cc;
+#endif
+ QObject *target = stack.top();
+ new QmlVMEMetaObject(target, synthesizedMetaObjects.at(instr.storeMeta.data), &comp->primitives, instr.storeMeta.slotData, comp);
+ }
+ break;
+
+ case QmlInstruction::AssignCustomType:
+ {
+ QObject *target = stack.top();
+ void *a[1];
+ QmlCompiledComponent::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex);
+ const QString &primitive = primitives.at(data.index);
+ QmlMetaType::StringConverter converter =
+ QmlMetaType::customStringConverter(data.type);
+ QVariant v = (*converter)(primitive);
+
+ QMetaProperty prop =
+ target->metaObject()->property(instr.assignCustomType.propertyIndex);
+ if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type))
+ VME_EXCEPTION("Cannot assign value" << primitive << "to property" << prop.name());
+
+ a[0] = (void *)v.data();
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.assignCustomType.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::AssignSignal:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignSignal> cc;
+#endif
+ // Fixup instruction
+ QObject *target = stack.top();
+ int sigIdx = instr.assignSignal.signal;
+ const QByteArray &pr = datas.at(sigIdx);
+
+ QmlMetaProperty prop(target, QLatin1String(pr));
+ if (prop.type() & QmlMetaProperty::SignalProperty) {
+ int coreIdx = prop.coreIndex();
+ int primRef = instr.assignSignal.value;
+ instr.type = QmlInstruction::StoreSignal;
+ instr.storeSignal.signalIndex = coreIdx;
+ instr.storeSignal.value = primRef;
+ --ii;
+ } else if (prop.type() & QmlMetaProperty::Property) {
+ int prop = sigIdx;
+ int primRef = instr.assignSignal.value;
+ instr.type = QmlInstruction::AssignConstant;
+ instr.assignConstant.property = prop;
+ instr.assignConstant.constant = primRef;
+ --ii;
+ } else {
+ VME_EXCEPTION("Cannot assign a signal to property" << pr);
+ }
+ }
+ break;
+
+ case QmlInstruction::AssignSignalObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignSignalObject> cc;
+#endif
+ // XXX optimize
+
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+ int sigIdx = instr.assignSignalObject.signal;
+ const QByteArray &pr = datas.at(sigIdx);
+
+ QmlMetaProperty prop(target, QLatin1String(pr));
+ if (prop.type() & QmlMetaProperty::SignalProperty) {
+
+ QMetaMethod method = QmlMetaType::defaultMethod(assign);
+ if (method.signature() == 0)
+ VME_EXCEPTION("Cannot assign object type" << assign->metaObject()->className() << "with no default method");
+
+ if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
+ VME_EXCEPTION("Cannot connect mismatched signal/slot" << method.signature() << prop.method().signature());
+
+ QMetaObject::connect(target, prop.coreIndex(), assign, method.methodIndex());
+
+ } else if (prop.type() & QmlMetaProperty::Property) {
+ instr.type = QmlInstruction::AssignObject;
+ instr.assignObject.castValue = 0;
+ instr.assignObject.property = sigIdx;
+ --ii;
+ } else {
+ VME_EXCEPTION("Cannot assign an object to signal property" << pr);
+ }
+
+
+ }
+ break;
+
+ case QmlInstruction::StoreSignal:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreSignal> cc;
+#endif
+ QObject *target = stack.top();
+ // XXX scope
+ QMetaMethod signal =
+ target->metaObject()->method(instr.storeSignal.signalIndex);
+
+ if (signal.parameterTypes().isEmpty()) {
+ (void *)new QmlBoundSignal(QmlContext::activeContext(), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target);
+ } else {
+ (void *)new QmlBoundSignalProxy(new QmlContext(QmlContext::activeContext(), target), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target);
+ }
+ }
+ break;
+
+ case QmlInstruction::AssignConstant:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignConstant> cc;
+#endif
+ // Fixup instruction
+ QObject *target = stack.top();
+ int propIdx = instr.assignConstant.property;
+ int idx = instr.assignConstant.constant;
+ QByteArray pr;
+ if (propIdx == -1) {
+ pr = QmlMetaType::defaultProperty(target).name();
+ if (pr.isEmpty())
+ VME_EXCEPTION("Cannot resolve defalt property on type" << target->metaObject()->className());
+ } else {
+ pr = datas.at(propIdx);
+ }
+
+ int coreIdx = qIndexOfProperty(target, pr);
+
+ if (coreIdx != -1) {
+ QMetaProperty prop =
+ target->metaObject()->property(coreIdx);
+ bool replace = !prop.isDynamic();
+
+ QmlInstruction *writeInstr = 0;
+ QmlInstruction dummy;
+ if (replace) {
+ writeInstr = &instr;
+ } else {
+ writeInstr = &dummy;
+ dummy = instr;
+ }
+
+ QmlCompiler::StoreInstructionResult r = QmlCompiler::generateStoreInstruction(*comp, *writeInstr, prop,
+ coreIdx, idx, &primitives.at(idx));
+ if (r != QmlCompiler::Ok) {
+ if (prop.isEnumType()){
+ VME_EXCEPTION(primitives.at(idx) << "is not a valid enumeration value");
+ } else if (r == QmlCompiler::UnknownType) {
+ VME_EXCEPTION("Property" << prop.name() << "is of an unknown type");
+ } else if (r == QmlCompiler::InvalidData) {
+ VME_EXCEPTION("Cannot assign value" << primitives.at(idx) << "to property" << prop.name());
+ } else if (r == QmlCompiler::ReadOnly) {
+ VME_EXCEPTION("Cannot assign value" << primitives.at(idx) << "to read-only property" << prop.name());
+ } else {
+ VME_EXCEPTION("Invalid property assignment for property" << prop.name());
+ }
+ } else {
+ runStoreInstruction(stack, *writeInstr, comp);
+ }
+
+ } else {
+ VME_EXCEPTION("Unknown property" << pr);
+ }
+ }
+ break;
+
+ case QmlInstruction::TryBeginObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrTryBeginObject> cc;
+#endif
+ QObject *target = stack.top();
+ QmlParserStatus *status =
+ qobject_cast<QmlParserStatus *>(target);
+
+ if (status) {
+ instr.type = QmlInstruction::BeginObject;
+ instr.begin.castValue = int(reinterpret_cast<char *>(status) - reinterpret_cast<char *>(target));
+ --ii;
+ } else {
+ instr.type = QmlInstruction::NoOp;
+ }
+ }
+ break;
+
+ case QmlInstruction::BeginObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrBeginObject> cc;
+#endif
+ QObject *target = stack.top();
+ QmlParserStatus *status = reinterpret_cast<QmlParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue);
+ parserStatus.append(status);
+ status->d = &parserStatus.values[parserStatus.count - 1];
+
+ status->classBegin();
+ }
+ break;
+
+ case QmlInstruction::TryCompleteObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrTryCompleteObject> cc;
+#endif
+ QObject *target = stack.top();
+ QmlParserStatus *status =
+ qobject_cast<QmlParserStatus *>(target);
+
+ if (status) {
+ instr.type = QmlInstruction::CompleteObject;
+ instr.complete.castValue = int(reinterpret_cast<char *>(status) - reinterpret_cast<char *>(target));
+ --ii;
+ } else {
+ instr.type = QmlInstruction::NoOp;
+ }
+ }
+ break;
+
+ case QmlInstruction::CompleteObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrCompleteObject> cc;
+#endif
+ QObject *target = stack.top();
+ QmlParserStatus *status = reinterpret_cast<QmlParserStatus *>(reinterpret_cast<char *>(target) + instr.complete.castValue);
+ status->classComplete();
+ }
+ break;
+
+ case QmlInstruction::AssignCompiledBinding:
+ case QmlInstruction::AssignBinding:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignBinding> cc;
+#endif
+ QObject *target = stack.top();
+ const QByteArray &pr = datas.at(instr.fetch.property);
+ int idx = qIndexOfProperty(target, pr);
+
+ // XXX - need to check if the type is QmlBindableValue*
+ if (idx == -1) {
+ VME_EXCEPTION("Unknown property" << pr);
+ } else {
+ if (QmlInstruction::AssignCompiledBinding == instr.type)
+ instr.type = QmlInstruction::StoreCompiledBinding;
+ else
+ instr.type = QmlInstruction::StoreBinding;
+ instr.assignBinding.property = idx;
+ instr.assignBinding.category = QmlMetaProperty::Unknown;
+ }
+ ii--;
+ }
+ break;
+
+ case QmlInstruction::AssignValueSource:
+ {
+ QObject *target = stack.at(stack.count() - 2);
+ int propIdx = instr.assignValueSource.property;
+ QByteArray pr;
+ if (propIdx == -1) {
+ pr = QmlMetaType::defaultProperty(target).name();
+ if (pr.isEmpty())
+ VME_EXCEPTION("Unable to resolve default property");
+ } else {
+ pr = datas.at(propIdx);
+ }
+
+ int coreIdx = qIndexOfProperty(target, pr);
+ if (coreIdx != -1) {
+ instr.type = QmlInstruction::StoreValueSource;
+ instr.assignValueSource.property = coreIdx;
+ ii--;
+ } else {
+ VME_EXCEPTION("Unknown property" << pr);
+ }
+ }
+ break;
+
+ case QmlInstruction::PushProperty:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrPushProperty> cc;
+#endif
+ QObject *target = stack.top();
+ QmlMetaProperty mp(target, instr.pushProperty.property,
+ QmlMetaProperty::Object);
+ pushedProperties.push(mp);
+ }
+ break;
+
+ case QmlInstruction::StoreCompiledBinding:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreCompiledBinding> cc;
+#endif
+ QObject *target = stack.top();
+ QObject *context =
+ stack.at(stack.count() - 1 - instr.assignBinding.context);
+
+ QmlMetaProperty mp(target, instr.assignBinding.property,
+ (QmlMetaProperty::PropertyCategory)instr.assignBinding.category);
+ if (!mp.isWritable())
+ VME_EXCEPTION("Cannot assign a binding to read-only property" << mp.name());
+
+ QmlBindableValue *bind = new QmlBindableValue((void *)datas.at(instr.assignBinding.value).constData(), comp, context, 0);
+ bindValues.append(bind);
+ QmlBindableValuePrivate *p =
+ static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bind));
+ p->mePtr = &bindValues.values[bindValues.count - 1];
+ QFx_setParent_noEvent(bind, target);
+
+ bind->setTarget(mp);
+ }
+ break;
+
+ case QmlInstruction::StoreBinding:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreBinding> cc;
+#endif
+ QObject *target = stack.top();
+ QObject *context =
+ stack.at(stack.count() - 1 - instr.assignBinding.context);
+
+ QmlMetaProperty mp(target, instr.assignBinding.property,
+ (QmlMetaProperty::PropertyCategory)instr.assignBinding.category);
+ if (!mp.isWritable())
+ VME_EXCEPTION("Cannot assign a binding to read-only property" << mp.name());
+
+ QmlBindableValue *bind = new QmlBindableValue(primitives.at(instr.assignBinding.value), context, false);
+ bindValues.append(bind);
+ QmlBindableValuePrivate *p =
+ static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bind));
+ p->mePtr = &bindValues.values[bindValues.count - 1];
+ QFx_setParent_noEvent(bind, target);
+
+ bind->setTarget(mp);
+ }
+ break;
+
+ case QmlInstruction::StoreValueSource:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreValueSource> cc;
+#endif
+ QObject *assign = stack.pop();
+ QmlPropertyValueSource *vs =
+ static_cast<QmlPropertyValueSource *>(assign);
+ QObject *target = stack.top();
+ vs->setParent(target);
+ vs->setTarget(QmlMetaProperty(target, instr.assignValueSource.property));
+ }
+ break;
+
+ case QmlInstruction::AssignObjectList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignObjectList> cc;
+#endif
+ QObject *assign = stack.pop();
+ const ListInstance &list = qliststack.top();
+ if (list.qmlListInterface) {
+ int type = list.type;
+
+ void *d = 0;
+ void *ptr = 0;
+ bool found = false;
+
+ if (QmlMetaType::isInterface(type)) {
+ const char *iid = QmlMetaType::interfaceIId(type);
+ if (iid)
+ ptr = assign->qt_metacast(iid);
+ if (ptr) {
+ d = &ptr;
+ found = true;
+ }
+ } else {
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *assignMo = assign->metaObject();
+ while(!found && assignMo) {
+ if (assignMo == mo)
+ found = true;
+ else
+ assignMo = assignMo->superClass();
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ d = (void *)&assign;
+ }
+
+
+ if (!found)
+ VME_EXCEPTION("Cannot assign object to list");
+
+ list.qmlListInterface->append(d);
+
+ } else {
+ int type = list.type;
+
+ if (QmlMetaType::isInterface(type)) {
+ void *ptr = 0;
+ const char *iid = QmlMetaType::interfaceIId(type);
+ if (iid)
+ ptr = assign->qt_metacast(iid);
+ QVariant v(list.type, &ptr);
+ QmlMetaType::append(list.list, v);
+ } else {
+ QVariant v = QmlMetaType::fromObject(assign, list.type);
+ QmlMetaType::append(list.list, v);
+ }
+ }
+ }
+ break;
+
+ case QmlInstruction::AssignObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignObject> cc;
+#endif
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+
+ QByteArray property;
+ if (instr.assignObject.property == -1) {
+ // XXX - optimize!
+ property =
+ QmlMetaType::defaultProperty(target).name();
+ } else {
+ property = datas.at(instr.assignObject.property);
+ }
+
+ int coreIdx = qIndexOfProperty(target, property);
+
+ if (coreIdx != -1) {
+ QMetaProperty prop =
+ target->metaObject()->property(coreIdx);
+ int t = prop.userType();
+ // XXX - optimize!
+ if (QmlMetaType::isList(t)) {
+ QVariant list = prop.read(target);
+ int listtype = QmlMetaType::listType(t);
+ QVariant v = QmlMetaType::fromObject(assign, listtype);
+ QmlMetaType::append(list, v);
+ } else if (QmlMetaType::isQmlList(t)) {
+
+ // XXX - optimize!
+ QVariant list = prop.read(target);
+ QmlPrivate::ListInterface *li =
+ *(QmlPrivate::ListInterface **)list.constData();
+
+ int type = li->type();
+
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *assignMo = assign->metaObject();
+ bool found = false;
+ while(!found && assignMo) {
+ if (assignMo == mo)
+ found = true;
+ else
+ assignMo = assignMo->superClass();
+ }
+
+ if (!found)
+ VME_EXCEPTION("Cannot assign object to list");
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ void *d = (void *)&assign;
+ li->append(d);
+
+ } else if (QmlMetaType::isInterface(t)) {
+ const char *iid = QmlMetaType::interfaceIId(t);
+ bool ok = false;
+ if (iid) {
+ void *ptr = assign->qt_metacast(iid);
+ if (ptr) {
+ void *a[1];
+ a[0] = &ptr;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ coreIdx, a);
+ ok = true;
+ }
+ }
+
+ if (!ok)
+ VME_EXCEPTION("Cannot assign object to interface property" << property);
+
+ } else if (prop.userType() == -1 /* means qvariant */) {
+ prop.write(target, qVariantFromValue(assign));
+ } else {
+ const QMetaObject *propmo =
+ QmlMetaType::rawMetaObjectForType(t);
+
+ bool isPropertyValue = false;
+ bool isAssignable = false;
+ const QMetaObject *c = assign->metaObject();
+ while(c) {
+ isPropertyValue = isPropertyValue || (c == &QmlPropertyValueSource::staticMetaObject);
+ isAssignable = isAssignable || (c == propmo);
+ c = c->superClass();
+ }
+
+ if (isAssignable) {
+ // XXX - optimize!
+ QVariant v = QmlMetaType::fromObject(assign, t);
+ prop.write(target, v);
+ } else if (isPropertyValue) {
+ QmlPropertyValueSource *vs =
+ static_cast<QmlPropertyValueSource *>(assign);
+ vs->setParent(target);
+ vs->setTarget(QmlMetaProperty(target, coreIdx));
+ } else {
+ VME_EXCEPTION("Cannot assign to" << property);
+ }
+ }
+
+
+ } else {
+ if (instr.assignObject.property == -1) {
+ VME_EXCEPTION("Cannot assign to default property");
+ } else {
+ VME_EXCEPTION("Cannot assign to non-existant property" << property);
+ }
+ }
+
+ }
+ break;
+
+ case QmlInstruction::FetchAttached:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrFetchAttached> cc;
+#endif
+ QObject *target = stack.top();
+
+ QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target);
+
+ if (!qmlObject)
+ VME_EXCEPTION("Unable to create attached object");
+
+ stack.push(qmlObject);
+ }
+ break;
+
+ case QmlInstruction::FetchQmlList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrFetchQmlList> cc;
+#endif
+ QObject *target = stack.top();
+
+ void *a[1];
+ // We know that QmlList<*> can be converted to
+ // QmlPrivate::ListInterface
+ QmlPrivate::ListInterface *list = 0;
+ a[0] = &list;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetchQmlList.property, a);
+ if (!list)
+ VME_EXCEPTION("Cannot assign to null list");
+
+ qliststack.push(ListInstance(list, instr.fetchQmlList.type));
+ }
+ break;
+
+ case QmlInstruction::FetchQList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrFetchQList> cc;
+#endif
+ QObject *target = stack.top();
+ QMetaProperty prop =
+ target->metaObject()->property(instr.fetch.property);
+ QVariant v = prop.read(target);
+ qliststack.push(ListInstance(v, QmlMetaType::listType(prop.userType())));
+ }
+ break;
+
+ case QmlInstruction::ResolveFetchObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrResolveFetchObject> cc;
+#endif
+ QObject *target = stack.top();
+ const QByteArray &pr = datas.at(instr.fetch.property);
+ int idx = qIndexOfProperty(target, pr);
+ if (idx == -1)
+ VME_EXCEPTION("Cannot resolve property" << pr);
+ QMetaProperty prop = target->metaObject()->property(idx);
+ instr.type = QmlInstruction::FetchObject;
+ instr.fetch.property = idx;
+ if (QmlMetaType::isObject(prop.userType())) {
+ instr.fetch.isObject = true;
+ } else if (prop.userType() == -1) {
+ instr.fetch.isObject = false;
+ } else {
+ VME_EXCEPTION("Cannot set properties on" << prop.name() << "as it is of unknown type");
+ }
+ ii--;
+ }
+ break;
+
+ case QmlInstruction::FetchObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrFetchObject> cc;
+#endif
+ QObject *target = stack.top();
+
+ QObject *obj = 0;
+ if (instr.fetch.isObject) {
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ void *a[1];
+ a[0] = &obj;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetch.property, a);
+ } else {
+ void *a[1];
+ QVariant var;
+ a[0] = &var;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetch.property, a);
+ obj = QmlMetaType::toQObject(var);
+
+ }
+
+ if (!obj)
+ VME_EXCEPTION("Cannot set properties on" << target->metaObject()->property(instr.fetch.property).name() << "as it is null");
+
+ stack.push(obj);
+ }
+ break;
+
+ case QmlInstruction::PopQList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrPopQList> cc;
+#endif
+ qliststack.pop();
+ }
+ break;
+
+ case QmlInstruction::PopFetchedObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrPopFetchedObject> cc;
+#endif
+ stack.pop();
+ }
+ break;
+
+ case QmlInstruction::AssignStackObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignStackObject> cc;
+#endif
+
+ QObject *obj = savedObjects[instr.assignStackObject.object];
+ const QmlMetaProperty &prop =
+ pushedProperties.at(instr.assignStackObject.property);
+
+
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(prop.propertyType());
+ const QMetaObject *assignMo = obj->metaObject();
+
+ bool found = false;
+ while(!found && assignMo) {
+ if (assignMo == mo)
+ found = true;
+ else
+ assignMo = assignMo->superClass();
+ }
+
+ if (!found)
+ VME_EXCEPTION("Unable to assign object");
+
+ instr.type = QmlInstruction::StoreStackObject;
+ --ii;
+ }
+ break;
+
+ case QmlInstruction::StoreStackObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreStackObject> cc;
+#endif
+
+ const QmlMetaProperty &prop =
+ pushedProperties.at(instr.assignStackObject.property);
+ QObject *obj = savedObjects[instr.assignStackObject.object];
+
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ void *a[1];
+ a[0] = (void *)&obj;
+ QMetaObject::metacall(prop.object(), QMetaObject::WriteProperty,
+ prop.coreIndex(), a);
+ }
+ break;
+
+ case QmlInstruction::NoOp:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrNoOp> cc;
+#endif
+ }
+ break;
+
+ default:
+ qFatal("QmlCompiledComponent: Internal error - unknown instruction %d", instr.type);
+ break;
+ }
+ }
+ }
+
+ if (isError()) {
+ if (!stack.isEmpty()) {
+ delete stack.at(0);
+ }
+
+ QmlEnginePrivate::clear(bindValues);
+ QmlEnginePrivate::clear(parserStatus);
+ qWarning() << errors().at(0);
+ return 0;
+ }
+
+ QmlEnginePrivate *ep = ctxt->engine()->d_func();
+ if (bindValues.count)
+ ep->bindValues << bindValues;
+ if (parserStatus.count)
+ ep->parserStatus << parserStatus;
+
+ comp->dumpPost();
+
+ if (savedObjects)
+ delete [] savedObjects;
+
+ if (stack.isEmpty())
+ return 0;
+ else
+ return stack.top();
+ return 0;
+}
+
+bool QmlVME::isError() const
+{
+ return !vmeErrors.isEmpty();
+}
+
+QList<QmlError> QmlVME::errors() const
+{
+ return vmeErrors;
+}
+
+void QmlVME::runStoreInstruction(QStack<QObject *> &stack,
+ QmlInstruction &instr,
+ QmlCompiledData *comp)
+{
+ const QList<QString> &primitives = comp->primitives;
+ const QList<int> &intData = comp->intData;
+ const QList<float> &floatData = comp->floatData;
+
+ switch(instr.type) {
+ case QmlInstruction::StoreVariant:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreVariant> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ // XXX - can be more efficient
+ QVariant v = QmlStringConverters::variantFromString(primitives.at(instr.storeString.value));
+ a[0] = (void *)&v;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeString.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreString:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreString> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ a[0] = (void *)&primitives.at(instr.storeString.value);
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeString.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreReal:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreReal> cc;
+#endif
+ QObject *target = stack.top();
+ qreal r = instr.storeReal.value;
+ void *a[1];
+ a[0] = &r;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeReal.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreBool:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreBool> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ a[0] = (void *)&instr.storeBool.value;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeBool.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreInteger:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreInteger> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ a[0] = (void *)&instr.storeInteger.value;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeReal.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreColor:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreColor> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QColor c = QColor::fromRgba(instr.storeColor.value);
+ a[0] = (void *)&c;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeColor.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreDate:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreDate> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QDate d = QDate::fromJulianDay(instr.storeDate.value);
+ a[0] = (void *)&d;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeDate.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreTime:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ //QFxCompilerTimer<QFxCompiler::InstrStoreTime> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QTime t;
+ t.setHMS(intData.at(instr.storeTime.valueIndex),
+ intData.at(instr.storeTime.valueIndex+1),
+ intData.at(instr.storeTime.valueIndex+2),
+ intData.at(instr.storeTime.valueIndex+3));
+ a[0] = (void *)&t;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeTime.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreDateTime:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ //QFxCompilerTimer<QFxCompiler::InstrStoreDateTime> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QTime t;
+ t.setHMS(intData.at(instr.storeDateTime.valueIndex+1),
+ intData.at(instr.storeDateTime.valueIndex+2),
+ intData.at(instr.storeDateTime.valueIndex+3),
+ intData.at(instr.storeDateTime.valueIndex+4));
+ QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t);
+ a[0] = (void *)&dt;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeDateTime.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StorePoint:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStorePoint> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1)).toPoint();
+ a[0] = (void *)&p;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StorePointF:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStorePoint> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QPointF p(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1));
+ a[0] = (void *)&p;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreSize:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreSize> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1)).toSize();
+ a[0] = (void *)&p;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreSizeF:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreSize> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QSizeF s(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1));
+ a[0] = (void *)&s;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreRect:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ //QFxCompilerTimer<QFxCompiler::InstrStoreRect> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QRect r = QRectF(floatData.at(instr.storeRect.valueIndex),
+ floatData.at(instr.storeRect.valueIndex+1),
+ floatData.at(instr.storeRect.valueIndex+2),
+ floatData.at(instr.storeRect.valueIndex+3)).toRect();
+ a[0] = (void *)&r;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRect.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreRectF:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ //QFxCompilerTimer<QFxCompiler::InstrStoreRect> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QRectF r(floatData.at(instr.storeRect.valueIndex),
+ floatData.at(instr.storeRect.valueIndex+1),
+ floatData.at(instr.storeRect.valueIndex+2),
+ floatData.at(instr.storeRect.valueIndex+3));
+ a[0] = (void *)&r;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRect.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreObject> cc;
+#endif
+ QObject *assignObj = stack.pop();
+ QObject *target = stack.top();
+
+ void *a[1];
+ void *obj = (void *)(((char *)assignObj) + instr.storeObject.cast);
+ a[0] = (void *)&obj;
+
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeObject.propertyIndex, a);
+ }
+ break;
+ default:
+ qFatal("QmlCompiledComponent: Internal error - unknown instruction %d", instr.type);
+ break;
+ }
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvme_p.h b/src/declarative/qml/qmlvme_p.h
new file mode 100644
index 0000000..f7e13d6
--- /dev/null
+++ b/src/declarative/qml/qmlvme_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLVME_P_H
+#define QMLVME_P_H
+
+#include <QString>
+#include <QStack>
+#include <qmlerror.h>
+class QObject;
+
+QT_BEGIN_NAMESPACE
+class QmlInstruction;
+class QmlCompiledComponent;
+class QmlCompiledData;
+class QmlContext;
+
+class QmlVME
+{
+public:
+ QmlVME();
+
+ QObject *run(QmlContext *, QmlCompiledComponent *, int start = -1, int end = -1);
+
+ bool isError() const;
+ QList<QmlError> errors() const;
+
+private:
+ void runStoreInstruction(QStack<QObject *> &stack,
+ QmlInstruction &, QmlCompiledData *);
+
+ QList<QmlError> vmeErrors;
+};
+
+QT_END_NAMESPACE
+#endif // QMLVME_P_H
diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp
new file mode 100644
index 0000000..58708cf
--- /dev/null
+++ b/src/declarative/qml/qmlvmemetaobject.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlvmemetaobject_p.h"
+#include <qml.h>
+#include <private/qmlrefcount_p.h>
+#include <QColor>
+#include <QDate>
+#include <QtCore/qlist.h>
+#include <QtCore/qdebug.h>
+#include <qmlexpression.h>
+
+
+QT_BEGIN_NAMESPACE
+QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj,
+ const QMetaObject *other,
+ QList<QString> *strData,
+ int slotData,
+ QmlRefCount *rc)
+: object(obj), ref(rc), slotData(strData), slotDataIdx(slotData)
+{
+ if (ref)
+ ref->addref();
+
+ *static_cast<QMetaObject *>(this) = *other;
+ this->d.superdata = obj->metaObject();
+ QObjectPrivate::get(obj)->metaObject = this;
+
+ baseProp = propertyOffset();
+ baseSig = methodOffset();
+ data = new QVariant[propertyCount() - baseProp];
+ vTypes.resize(propertyCount() - baseProp);
+
+ // ### Optimize
+ for (int ii = baseProp; ii < propertyCount(); ++ii) {
+ QMetaProperty prop = property(ii);
+ if ((int)prop.type() != -1) {
+ data[ii - baseProp] = QVariant((QVariant::Type)prop.userType());
+ } else {
+ vTypes.setBit(ii - baseProp, true);
+ }
+ }
+
+ baseSlot = -1;
+ slotCount = 0;
+ for (int ii = baseSig; ii < methodCount(); ++ii) {
+ QMetaMethod m = method(ii);
+ if (m.methodType() == QMetaMethod::Slot) {
+ if (baseSlot == -1)
+ baseSlot = ii;
+ } else {
+ if (baseSlot != -1) {
+ slotCount = ii - baseSlot;
+ break;
+ }
+ }
+ }
+ if(baseSlot != -1 && !slotCount)
+ slotCount = methodCount() - baseSlot;
+}
+
+QmlVMEMetaObject::~QmlVMEMetaObject()
+{
+ if (ref)
+ ref->release();
+ delete [] data;
+}
+
+int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) {
+ if (id >= baseProp) {
+ int propId = id - baseProp;
+ bool needActivate = false;
+
+ if (vTypes.testBit(propId)) {
+ if (c == QMetaObject::ReadProperty) {
+ *reinterpret_cast<QVariant *>(a[0]) = data[propId];
+ } else if (c == QMetaObject::WriteProperty) {
+ needActivate =
+ (data[propId] != *reinterpret_cast<QVariant *>(a[0]));
+ data[propId] = *reinterpret_cast<QVariant *>(a[0]);
+ }
+ } else {
+ if (c == QMetaObject::ReadProperty) {
+ switch(data[propId].type()) {
+ case QVariant::Int:
+ *reinterpret_cast<int *>(a[0]) = data[propId].toInt();
+ break;
+ case QVariant::Bool:
+ *reinterpret_cast<bool *>(a[0]) = data[propId].toBool();
+ break;
+ case QVariant::Double:
+ *reinterpret_cast<double *>(a[0]) = data[propId].toDouble();
+ break;
+ case QVariant::String:
+ *reinterpret_cast<QString *>(a[0]) = data[propId].toString();
+ break;
+ case QVariant::Color:
+ *reinterpret_cast<QColor *>(a[0]) = data[propId].value<QColor>();
+ break;
+ case QVariant::Date:
+ *reinterpret_cast<QDate *>(a[0]) = data[propId].toDate();
+ break;
+ default:
+ qFatal("Unknown type");
+ break;
+ }
+ } else if (c == QMetaObject::WriteProperty) {
+
+ QVariant value = QVariant((QVariant::Type)data[propId].type(), a[0]);
+ needActivate = (data[propId] != value);
+ data[propId] = value;
+ }
+ }
+
+ if (c == QMetaObject::WriteProperty && needActivate) {
+ activate(object, baseSig + propId, 0);
+ }
+
+ return id;
+ }
+ } else if(c == QMetaObject::InvokeMetaMethod) {
+ if(id >= baseSlot && id < (baseSlot + slotCount)) {
+ int idx = id - baseSlot + slotDataIdx;
+ QmlContext *ctxt = qmlContext(object);
+ QmlExpression expr(ctxt, slotData->at(idx), object);
+ expr.setTrackChange(false);
+ expr.value();
+ return id;
+ }
+ }
+
+ return object->qt_metacall(c, id, a);
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h
new file mode 100644
index 0000000..d8ed242
--- /dev/null
+++ b/src/declarative/qml/qmlvmemetaobject_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLVMEMETAOBJECT_P_H
+#define QMLVMEMETAOBJECT_P_H
+
+#include <qml.h>
+#include <QMetaObject>
+#include <QBitArray>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+class QmlRefCount;
+class QmlVMEMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QmlVMEMetaObject(QObject *, const QMetaObject *, QList<QString> *, int slotData, QmlRefCount * = 0);
+ ~QmlVMEMetaObject();
+
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+
+private:
+ QObject *object;
+ QmlRefCount *ref;
+ int baseProp;
+ int baseSig;
+ int baseSlot;
+ int slotCount;
+ QVariant *data;
+ QBitArray vTypes;
+ QList<QString> *slotData;
+ int slotDataIdx;
+};
+
+QT_END_NAMESPACE
+#endif // QMLVMEMETAOBJECT_P_H
diff --git a/src/declarative/qml/script/generator/generator.pro b/src/declarative/qml/script/generator/generator.pro
new file mode 100644
index 0000000..1b2a4c7
--- /dev/null
+++ b/src/declarative/qml/script/generator/generator.pro
@@ -0,0 +1,11 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Mon Apr 2 20:15:52 2007
+######################################################################
+
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
diff --git a/src/declarative/qml/script/generator/main.cpp b/src/declarative/qml/script/generator/main.cpp
new file mode 100644
index 0000000..a841cbc
--- /dev/null
+++ b/src/declarative/qml/script/generator/main.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QList>
+#include <QByteArray>
+
+
+QT_BEGIN_NAMESPACE
+struct Keyword {
+ const char *lexem;
+ const char *token;
+};
+
+struct State
+{
+ State(const char* token) : token(token)
+ {
+ ::memset(next, 0, sizeof(next));
+ }
+ State(const State &other) : token(other.token)
+ {
+ ::memcpy(next, other.next, sizeof(next));
+ }
+ State &operator=(const State &other)
+ {
+ token = other.token;
+ ::memcpy(next, other.next, sizeof(next));
+ return *this;
+ }
+
+ QByteArray token;
+ int next[128];
+};
+
+Keyword keywords[] =
+{
+ {"<", "LANGLE" },
+ {">", "RANGLE" },
+ {"+", "PLUS" },
+ {"-", "MINUS" },
+ {"*", "STAR" },
+ {"==", "EQUALS" },
+ {"&&", "AND" },
+ {".", "DOT"},
+ {"true", "TOKEN_TRUE"},
+ {"false", "TOKEN_FALSE"},
+ {" ", "WHITESPACE"},
+ {"\t", "WHITESPACE"},
+ {0, 0}
+};
+
+bool is_character(char s)
+{
+ return (s >= 'a' && s <= 'z') ||
+ (s >= 'A' && s <= 'Z') ||
+ (s >= '0' && s <= '9') ||
+ s == '_';
+}
+
+void newState(QList<State> &states, const char *token, const char *lexem)
+{
+ int state = 0;
+ bool character = is_character(*lexem);
+
+ while(*lexem) {
+ int next = states[state].next[(int)*lexem];
+
+ if (!next) {
+ next = states.size();
+ states += State(character?"CHARACTER":"INCOMPLETE");
+ states[state].next[(int)*lexem] = next;
+ }
+
+ state = next;
+ ++lexem;
+ character = character && is_character(*lexem);
+ }
+
+ states[state].token = token;
+}
+
+void newState(QList<State> &states, const char *token, char lexem)
+{
+ int next = states[0].next[(int)lexem];
+ if (!next) {
+ next = states.size();
+ states += State(token);
+ states[0].next[(int)lexem] = next;
+ } else {
+ states[next].token = token;
+ }
+}
+
+int main()
+{
+ QList<State> states;
+ states += State("NOTOKEN");
+
+ // identifiers
+ for (int cc = 'a'; cc <= 'z'; ++cc)
+ newState(states, "CHARACTER", cc);
+ for (int cc = 'A'; cc <= 'Z'; ++cc)
+ newState(states, "CHARACTER", cc);
+ newState(states, "CHARACTER", '_');
+
+ // add digits
+ for (int cc = '0'; cc <= '9'; ++cc)
+ newState(states, "DIGIT", cc);
+
+ // keywords
+ for (int ii = 0; keywords[ii].lexem; ++ii)
+ newState(states, keywords[ii].token, keywords[ii].lexem);
+
+ ::printf("static const struct\n{\n"
+ " Token token;\n"
+ " char next[128];\n"
+ "} keywords[] = {\n");
+
+ for (int ii = 0; ii < states.size(); ++ii) {
+ printf("%s { %s, { ", ii?",\n":"", states[ii].token.data());
+ for (int jj = 0; jj < 128; jj++)
+ printf("%s%d", jj?",":"", states[ii].next[jj]);
+ printf(" } }");
+ }
+
+ printf("\n};\n");
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/script/instructions.h b/src/declarative/qml/script/instructions.h
new file mode 100644
index 0000000..a21cbce
--- /dev/null
+++ b/src/declarative/qml/script/instructions.h
@@ -0,0 +1,32 @@
+#ifndef _INSTRUCTIONS_H_
+#define _INSTRUCTIONS_H_
+
+struct ScriptInstruction {
+ enum {
+ Load, // fetch
+ Fetch, // fetch
+
+ Add, // NA
+ Subtract, // NA
+ Multiply, // NA
+ Equals, // NA
+ And, // NA
+
+ Int, // integer
+ Bool, // boolean
+ } type;
+
+ union {
+ struct {
+ int idx;
+ } fetch;
+ struct {
+ int value;
+ } integer;
+ struct {
+ bool value;
+ } boolean;
+ };
+};
+
+#endif // _INSTRUCTIONS_H_
diff --git a/src/declarative/qml/script/keywords.cpp b/src/declarative/qml/script/keywords.cpp
new file mode 100644
index 0000000..4cde65b
--- /dev/null
+++ b/src/declarative/qml/script/keywords.cpp
@@ -0,0 +1,89 @@
+static const struct
+{
+ Token token;
+ char next[128];
+} keywords[] = {
+ { NOTOKEN, { 0,0,0,0,0,0,0,0,0,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,81,0,0,0,0,0,71,0,0,0,68,66,0,67,73,0,54,55,56,57,58,59,60,61,62,63,0,0,64,69,65,0,0,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,0,0,0,0,53,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,77,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,74,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { LANGLE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { RANGLE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { PLUS, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { MINUS, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { STAR, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { INCOMPLETE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { EQUALS, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { INCOMPLETE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { AND, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DOT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,75,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { TOKEN_TRUE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,79,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { TOKEN_FALSE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { WHITESPACE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { WHITESPACE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }
+};
diff --git a/src/declarative/qml/script/lexer.cpp b/src/declarative/qml/script/lexer.cpp
new file mode 100644
index 0000000..d3ef935
--- /dev/null
+++ b/src/declarative/qml/script/lexer.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QByteArray>
+#include "lexer.h"
+#include "keywords.cpp"
+#include <QDebug>
+
+
+QT_BEGIN_NAMESPACE
+QList<LexerToken> tokenize(const char *text)
+{
+ QList<LexerToken> rv;
+
+ int lineNo = 0;
+ int charNo = 0;
+ int state = 0;
+ int tokenStart = 0;
+ bool other = false;
+
+ const char *textprog = text;
+
+ bool done = false;
+ while (!done) {
+ char textchar = *textprog;
+ done = !textchar;
+
+ if (other) {
+ if (keywords[state].next[(int)textchar]) {
+
+ // Do other token
+ LexerToken token;
+ token.token = OTHER;
+ token.start = tokenStart;
+ token.end = textprog - text - 1;
+ token.line = lineNo + 1;
+ token.offset = charNo - (token.end - token.start);
+ tokenStart = token.end + 1;
+ rv.append(token);
+ other = false;
+
+ } else {
+ goto continue_loop;
+ }
+ }
+
+ if (keywords[state].next[(int)textchar]) {
+
+ state = keywords[state].next[(int)textchar];
+
+ } else if (0 == state ||
+ keywords[state].token == INCOMPLETE) {
+
+ other = true;
+ if (keywords[state].token == INCOMPLETE) {
+ state = 0;
+ continue;
+ }
+
+ } else {
+
+ // Token completed
+ Token tokenType = keywords[state].token;
+ bool tokenCollapsed = false;
+ if (tokenType == CHARACTER ||
+ tokenType == DIGIT ||
+ tokenType == WHITESPACE) {
+
+ Token lastTokenType =
+ rv.isEmpty()?NOTOKEN:rv.last().token;
+ if (tokenType == lastTokenType) {
+
+ rv.last().end = textprog - text - 1;
+ tokenStart = rv.last().end + 1;
+
+ tokenCollapsed = true;
+ }
+ }
+
+ if (!tokenCollapsed) {
+ LexerToken token;
+ token.token = keywords[state].token;
+ token.start = tokenStart;
+ token.end = textprog - text - 1;
+ token.line = lineNo + 1;
+ token.offset = charNo - (token.end - token.start);
+ tokenStart = token.end + 1;
+ rv.append(token);
+ }
+
+ state = keywords[0].next[(int)textchar];
+ if (0 == state)
+ other = true;
+ }
+
+continue_loop:
+ // Reset error reporting variables
+ if (textchar == '\n') {
+ ++lineNo;
+ charNo = 0;
+ } else {
+ charNo++;
+ }
+
+ // Increment ptrs
+ ++textprog;
+ }
+
+ if (other && ((textprog - text - 1) != tokenStart)) {
+ // Do other token
+ LexerToken token;
+ token.token = OTHER;
+ token.start = tokenStart;
+ token.end = textprog - text - 1;
+ token.line = lineNo + 1;
+ token.offset = charNo - (token.end - token.start);
+ tokenStart = token.end + 1;
+ rv.append(token);
+ other = false;
+ }
+ return rv;
+}
+
+void dumpTokens(const char *text, const QList<LexerToken> &tokens)
+{
+ for (int ii = 0; ii < tokens.count(); ++ii) {
+ QByteArray ba(text + tokens.at(ii).start, tokens.at(ii).end - tokens.at(ii).start + 1);
+ qWarning() << tokens.at(ii).line << ":" << tokens.at(ii).offset << tokenToString(tokens.at(ii).token) << "(" << tokens.at(ii).start << "-" << tokens.at(ii).end << ")" << ba;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/script/lexer.h b/src/declarative/qml/script/lexer.h
new file mode 100644
index 0000000..7781ee8
--- /dev/null
+++ b/src/declarative/qml/script/lexer.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LEXER_H
+#define LEXER_H
+
+#include <QList>
+#include "tokens.h"
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+struct LexerToken
+{
+ LexerToken() : token(NOTOKEN), start(-1), end(-1), line(-1), offset(-1) {}
+ LexerToken(const LexerToken &other) : token(other.token),
+ start(other.start),
+ end(other.end),
+ line(other.line),
+ offset(other.offset) {}
+ LexerToken &operator=(const LexerToken &other) {
+ token = other.token;
+ start = other.start;
+ end = other.end;
+ line = other.line;
+ offset = other.offset;
+ return *this;
+ }
+
+ Token token;
+ int start;
+ int end;
+ int line;
+ int offset;
+};
+
+QList<LexerToken> tokenize(const char *text);
+void dumpTokens(const char *text, const QList<LexerToken> &tokens);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/qml/script/qmlbasicscript.cpp b/src/declarative/qml/script/qmlbasicscript.cpp
new file mode 100644
index 0000000..e0a668a
--- /dev/null
+++ b/src/declarative/qml/script/qmlbasicscript.cpp
@@ -0,0 +1,914 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlbasicscript.h"
+#include "qmlbasicscript_p.h"
+#include "lexer.h"
+#include <QColor>
+#include <QDebug>
+#include <private/qmlengine_p.h>
+#include <private/qmlcontext_p.h>
+#include <QStack>
+#include <qfxperf.h>
+#include <private/qmlrefcount_p.h>
+
+
+QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS);
+
+class QmlBasicScriptPrivate
+{
+public:
+ enum Flags { OwnData = 0x00000001 };
+
+ int size;
+ int stateSize;
+ int instructionCount;
+ int exprLen;
+
+ ScriptInstruction *instructions() const { return (ScriptInstruction *)((char *)this + sizeof(QmlBasicScriptPrivate)); }
+
+ const char *expr() const
+ {
+ return (const char *)(instructions() + instructionCount);
+ }
+
+ const char *data() const
+ {
+ return (const char *)(instructions() + instructionCount) + exprLen + 1;
+ }
+
+ static unsigned int alignRound(int s)
+ {
+ if (s % 4)
+ s += 4 - (s % 4);
+ return s;
+ }
+};
+
+QDebug operator<<(QDebug lhs, const QmlBasicScriptNodeCache &rhs)
+{
+ switch(rhs.type) {
+ case QmlBasicScriptNodeCache::Invalid:
+ lhs << "Invalid";
+ break;
+ case QmlBasicScriptNodeCache::Core:
+ lhs << "Core" << rhs.object << rhs.core;
+ break;
+ case QmlBasicScriptNodeCache::Attached:
+ lhs << "Attached" << rhs.object << rhs.attached;
+ break;
+ case QmlBasicScriptNodeCache::Signal:
+ lhs << "Signal" << rhs.object << rhs.core;
+ break;
+ case QmlBasicScriptNodeCache::SignalProperty:
+ lhs << "SignalProperty" << rhs.object << rhs.core;
+ break;
+ case QmlBasicScriptNodeCache::Variant:
+ lhs << "Variant" << rhs.context;
+ break;
+ }
+
+ return lhs;
+}
+
+void QmlBasicScriptNodeCache::clear()
+{
+ object = 0;
+ metaObject = 0;
+ type = Invalid;
+}
+
+static QVariant toObjectOrVariant(const QVariant &v)
+{
+ switch(v.type()) {
+ case QVariant::String:
+ case QVariant::UInt:
+ case QVariant::Int:
+ case 135:
+ case QVariant::Double:
+ case QVariant::Color:
+ case QVariant::Bool:
+ default:
+ return v;
+ case QVariant::UserType:
+ {
+ QObject *o = QmlMetaType::toQObject(v);
+ if (o)
+ return qVariantFromValue(o);
+ else
+ return v;
+ }
+ break;
+ }
+}
+
+static QVariant fetch_value(QObject *o, int idx, int type)
+{
+ switch(type) {
+ case QVariant::String:
+ {
+ QString val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::UInt:
+ {
+ uint val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Int:
+ {
+ int val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case 135:
+ case QVariant::Double:
+ {
+ qreal val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Color:
+ {
+ QColor val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Bool:
+ {
+ bool val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ default:
+ {
+ if (QmlMetaType::isObject(type)) {
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ QObject *val = 0;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant::fromValue(val);
+ } else {
+ QVariant var = o->metaObject()->property(idx).read(o);
+ if (QmlMetaType::isObject(var.userType())) {
+ QObject *obj = 0;
+ obj = *(QObject **)var.data();
+ var = QVariant::fromValue(obj);
+ }
+ return var;
+ }
+ }
+ break;
+ };
+}
+
+QVariant QmlBasicScriptNodeCache::value(const char *name) const
+{
+ //QFxPerfTimer<QFxPerf::BasicScriptValue> pt;
+ switch(type) {
+ case Invalid:
+ break;
+ case Core:
+ return fetch_value(object, core, coreType);
+ break;
+ case Attached:
+ return qVariantFromValue(static_cast<QObject *>(attached));
+ break;
+ case Signal:
+ // XXX
+ Q_ASSERT(!"Not implemented");
+ break;
+ case SignalProperty:
+ break;
+ case Variant:
+ return context->propertyValues[contextIndex];
+ };
+ return QVariant();
+}
+
+struct QmlBasicScriptCompiler
+{
+ QmlBasicScriptCompiler()
+ : script(0), stateSize(0), src(0), idx(0) {}
+ QmlBasicScript *script;
+ QList<LexerToken> tokens;
+ int stateSize;
+ const char *src;
+ int idx;
+
+ bool compile();
+ bool compileExpr();
+
+ bool parseFetch();
+ bool parseName();
+ bool parseConstant();
+ void skipWhitespace();
+
+ QByteArray data;
+ QList<ScriptInstruction> bytecode;
+
+ QByteArray string(int, int);
+ Token token() const;
+ bool atEnd() const;
+ void adv();
+ int index() const;
+};
+
+/*!
+ \internal
+ \class QmlBasicScript
+ \brief The QmlBasicScript class provides a fast implementation of a limited subset of JavaScript bindings.
+
+ QmlBasicScript instances are used to accelerate binding. Instead of using
+ the slower, fully fledged JavaScript engine, many simple bindings can be
+ evaluated using the QmlBasicScript engine.
+
+ To see if the QmlBasicScript engine can handle a binding, call compile()
+ and check the return value, or isValid() afterwards.
+
+ To evaluate the binding, the QmlBasicScript instance needs some memory in
+ which to cache state. This may be allocated by calling newScriptState()
+ and destroyed by calling deleteScriptState(). The state data is then passed
+ to the run() method when evaluating the binding.
+
+ To further accelerate binding, QmlBasicScript can return a precompiled
+ version of itself that can be saved for future use. Call compileData() to
+ get an opaque pointer to the compiled state, and compileDataSize() for the
+ size of this data in bytes. This data can be saved and passed to future
+ instances of the QmlBasicScript constructor. The initial copy of compile
+ data is owned by the QmlBindScript instance on which compile() was called.
+*/
+
+/*!
+ Create a new QmlBasicScript instance.
+*/
+QmlBasicScript::QmlBasicScript()
+: flags(0), d(0), rc(0)
+{
+}
+
+/*!
+ Create a new QmlBasicScript instance from saved \a data.
+
+ \a data \b must be data previously acquired from calling compileData() on a
+ previously created QmlBasicScript instance. Any other data will almost
+ certainly cause the QmlBasicScript engine to crash.
+
+ \a data must continue to be valid throughout the QmlBasicScript instance
+ life. It does not assume ownership of the memory.
+
+ If \a owner is set, it is referenced on creation and dereferenced on
+ destruction of this instance.
+*/
+QmlBasicScript::QmlBasicScript(const char *data, QmlRefCount *owner)
+: flags(0), d((QmlBasicScriptPrivate *)data), rc(owner)
+{
+ if (rc) rc->addref();
+}
+
+/*!
+ Return the text of the script expression.
+ */
+QByteArray QmlBasicScript::expression() const
+{
+ if (!d)
+ return QByteArray();
+ else
+ return QByteArray(d->expr());
+}
+
+/*!
+ Destroy the script instance.
+*/
+QmlBasicScript::~QmlBasicScript()
+{
+ if (flags & QmlBasicScriptPrivate::OwnData)
+ free(d);
+ if (rc) rc->release();
+ d = 0;
+ rc = 0;
+}
+
+/*!
+ Clear this script. The object will then be in its initial state, as though
+ it were freshly constructed with default constructor.
+*/
+void QmlBasicScript::clear()
+{
+ if (flags & QmlBasicScriptPrivate::OwnData)
+ free(d);
+ if (rc) rc->release();
+ d = 0;
+ rc = 0;
+ flags = 0;
+}
+
+/*!
+ Return the script state memory for this script instance. This memory should
+ only be destroyed by calling deleteScriptState().
+ */
+void *QmlBasicScript::newScriptState()
+{
+ if (!d) {
+ return 0;
+ } else {
+ void *rv = ::malloc(d->stateSize * sizeof(QmlBasicScriptNodeCache));
+ ::memset(rv, 0, d->stateSize * sizeof(QmlBasicScriptNodeCache));
+ return rv;
+ }
+}
+
+/*!
+ Delete the \a data previously allocated by newScriptState().
+ */
+void QmlBasicScript::deleteScriptState(void *data)
+{
+ if (!data) return;
+ Q_ASSERT(d);
+ clearCache(data);
+ free(data);
+}
+
+/*!
+ Dump the script instructions to stderr for debugging.
+ */
+void QmlBasicScript::dump()
+{
+ if (!d)
+ return;
+
+ qWarning() << d->instructionCount << "instructions:";
+ const char *data = d->data();
+ for (int ii = 0; ii < d->instructionCount; ++ii) {
+ const ScriptInstruction &instr = d->instructions()[ii];
+
+ switch(instr.type) {
+ case ScriptInstruction::Load:
+ qWarning().nospace() << "LOAD\t\t" << instr.fetch.idx << "\t\t"
+ << QByteArray(data + instr.fetch.idx);
+ break;
+ case ScriptInstruction::Fetch:
+ qWarning().nospace() << "FETCH\t\t" << instr.fetch.idx << "\t\t"
+ << QByteArray(data + instr.fetch.idx);
+ break;
+ case ScriptInstruction::Add:
+ qWarning().nospace() << "ADD";
+ break;
+ case ScriptInstruction::Subtract:
+ qWarning().nospace() << "SUBTRACT";
+ break;
+ case ScriptInstruction::Multiply:
+ qWarning().nospace() << "MULTIPLY";
+ break;
+ case ScriptInstruction::Equals:
+ qWarning().nospace() << "EQUALS";
+ break;
+ case ScriptInstruction::Int:
+ qWarning().nospace() << "INT\t\t" << instr.integer.value;
+ break;
+ case ScriptInstruction::Bool:
+ qWarning().nospace() << "BOOL\t\t" << instr.boolean.value;
+ break;
+ default:
+ qWarning().nospace() << "UNKNOWN";
+ break;
+ }
+ }
+}
+
+/*!
+ Return true if this is a valid script binding, otherwise returns false.
+ */
+bool QmlBasicScript::isValid() const
+{
+ return d != 0;
+}
+
+/*!
+ Compile \a src and return true if the compilation is successful, otherwise
+ returns false.
+ */
+bool QmlBasicScript::compile(const QByteArray &src)
+{
+ bool rv = compile(src.constData());
+ return rv;
+}
+
+/*!
+ \overload
+
+ Compile \a src and return true if the compilation is successful, otherwise
+ returns false.
+ */
+bool QmlBasicScript::compile(const char *src)
+{
+ if (!src) return false;
+
+ QmlBasicScriptCompiler bsc;
+ bsc.script = this;
+ bsc.tokens = tokenize(src);
+ bsc.src = src;
+ // dumpTokens(src, bsc.tokens);
+
+ if (d) {
+ if (flags & QmlBasicScriptPrivate::OwnData)
+ free(d);
+ d = 0;
+ flags = 0;
+ }
+
+ if (bsc.compile()) {
+ int len = ::strlen(src);
+ flags = QmlBasicScriptPrivate::OwnData;
+ int size = sizeof(QmlBasicScriptPrivate) +
+ bsc.bytecode.count() * sizeof(ScriptInstruction) +
+ QmlBasicScriptPrivate::alignRound(bsc.data.count() + len + 1);
+ d = (QmlBasicScriptPrivate *) malloc(size);
+ d->size = size;
+ d->stateSize = bsc.stateSize;
+ d->instructionCount = bsc.bytecode.count();
+ d->exprLen = len;
+ ::memcpy((char *)d->expr(), src, len + 1);
+ for (int ii = 0; ii < d->instructionCount; ++ii)
+ d->instructions()[ii] = bsc.bytecode.at(ii);
+ ::memcpy((char *)d->data(), bsc.data.constData(), bsc.data.count());
+ }
+
+ return d != 0;
+}
+
+void QmlBasicScriptCompiler::skipWhitespace()
+{
+ while(idx < tokens.count() && tokens.at(idx).token == WHITESPACE)
+ ++idx;
+}
+
+bool QmlBasicScriptCompiler::compile()
+{
+ if (!compileExpr())
+ return false;
+
+ skipWhitespace();
+
+ if (atEnd())
+ return true;
+
+ int t = token();
+ if (t != AND)
+ return false;
+
+ adv();
+ skipWhitespace();
+ if (!compileExpr())
+ return false;
+
+ ScriptInstruction instr;
+ instr.type = ScriptInstruction::And;
+ bytecode.append(instr);
+
+ skipWhitespace();
+
+ return atEnd();
+}
+
+bool QmlBasicScriptCompiler::compileExpr()
+{
+ /*
+ EXPRESSION := <NAME><OPERATOR>[<CONSTANT>|<NAME>]
+ */
+
+ if (!parseName())
+ return false;
+
+ skipWhitespace();
+
+ if (atEnd())
+ return true;
+
+ int t = token();
+ switch(t) {
+ case PLUS:
+ case MINUS:
+ /*
+ case LANGLE:
+ case RANGLE:
+ */
+ case STAR:
+ case EQUALS:
+ break;
+ default:
+ return true;
+ }
+ adv();
+
+ skipWhitespace();
+
+ if (!parseConstant() &&
+ !parseName())
+ return false;
+
+ ScriptInstruction instr;
+ switch(t) {
+ case PLUS:
+ instr.type = ScriptInstruction::Add;
+ break;
+ case MINUS:
+ instr.type = ScriptInstruction::Subtract;
+ break;
+ case STAR:
+ instr.type = ScriptInstruction::Multiply;
+ break;
+ case EQUALS:
+ instr.type = ScriptInstruction::Equals;
+ break;
+ default:
+ break;
+ }
+ bytecode.append(instr);
+
+ skipWhitespace();
+
+ return true;
+}
+
+bool QmlBasicScriptCompiler::parseName()
+{
+ skipWhitespace();
+
+ bool named = false;
+ bool seenchar = false;
+ bool seendot = false;
+ int namestart = -1;
+ bool pushed = false;
+ while(!atEnd()) {
+ int t = token();
+ if (t == CHARACTER) {
+ named = true;
+ seendot = false;
+ seenchar = true;
+ namestart = index();
+ adv();
+ } else if (t == DIGIT) {
+ if (!seenchar) break;
+ adv();
+ } else if (t == DOT) {
+ seendot = true;
+ if (namestart == -1)
+ break;
+
+ seenchar = false;
+ QByteArray name = string(namestart, index() - 1);
+ int nref = data.count();
+ data.append(name);
+ data.append('\0');
+ ScriptInstruction instr;
+ if (pushed)
+ instr.type = ScriptInstruction::Fetch;
+ else
+ instr.type = ScriptInstruction::Load;
+ pushed = true;
+ instr.fetch.idx = nref;
+ bytecode.append(instr);
+ ++stateSize;
+ namestart = -1;
+ adv();
+ } else {
+ break;
+ }
+ }
+
+ if (namestart != -1) {
+ QByteArray name = string(namestart, index() - 1);
+ int nref = data.count();
+ data.append(name);
+ data.append('\0');
+ ScriptInstruction instr;
+ if (pushed)
+ instr.type = ScriptInstruction::Fetch;
+ else
+ instr.type = ScriptInstruction::Load;
+ pushed = true;
+ instr.fetch.idx = nref;
+ bytecode.append(instr);
+ ++stateSize;
+ }
+
+ if (seendot)
+ return false;
+ else
+ return named;
+}
+
+bool QmlBasicScriptCompiler::parseConstant()
+{
+ switch(token()) {
+ case DIGIT:
+ {
+ ScriptInstruction instr;
+ instr.type = ScriptInstruction::Int;
+ instr.integer.value = string(index(), index()).toUInt();
+ bytecode.append(instr);
+ adv();
+ }
+ break;
+ case TOKEN_TRUE:
+ case TOKEN_FALSE:
+ {
+ ScriptInstruction instr;
+ instr.type = ScriptInstruction::Bool;
+ instr.boolean.value = (token() == TOKEN_TRUE);
+ bytecode.append(instr);
+ adv();
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool QmlBasicScriptCompiler::atEnd() const
+{
+ return idx >= tokens.count();
+}
+
+Token QmlBasicScriptCompiler::token() const
+{
+ return tokens.at(idx).token;
+}
+
+void QmlBasicScriptCompiler::adv()
+{
+ ++idx;
+}
+
+int QmlBasicScriptCompiler::index() const
+{
+ return idx;
+}
+
+QByteArray QmlBasicScriptCompiler::string(int from, int to)
+{
+ QByteArray rv;
+ for (int ii = from; ii <= to; ++ii) {
+ const LexerToken &token = tokens.at(ii);
+ rv.append(QByteArray(src + token.start, token.end - token.start + 1));
+ }
+ return rv;
+}
+
+/*!
+ \internal
+*/
+void QmlBasicScript::clearCache(void *voidCache)
+{
+ QmlBasicScriptNodeCache *dataCache =
+ reinterpret_cast<QmlBasicScriptNodeCache *>(voidCache);
+
+ for (int ii = 0; ii < d->stateSize; ++ii) {
+ if (!dataCache[ii].isCore() && !dataCache[ii].isVariant() &&
+ dataCache[ii].object) {
+ QMetaObject::removeGuard(&dataCache[ii].object);
+ dataCache[ii].object = 0;
+ }
+ dataCache[ii].clear();
+ }
+}
+
+void QmlBasicScript::guard(QmlBasicScriptNodeCache &n)
+{
+ if (n.object) {
+ if (n.isVariant()) {
+ } else if (n.isCore()) {
+ n.metaObject =
+ n.object->metaObject();
+ } else {
+ QMetaObject::addGuard(&n.object);
+ }
+ }
+}
+
+bool QmlBasicScript::valid(QmlBasicScriptNodeCache &n, QObject *obj)
+{
+ return n.object == obj &&
+ (!n.isCore() || obj->metaObject() == n.metaObject);
+}
+
+
+/*!
+ \enum QmlBasicScript::CacheState
+ \value NoChange The query has not change. Any previous monitoring is still
+ valid.
+ \value Incremental The query has been incrementally changed. Any previous
+ monitoring is still valid, but needs to have the fresh properties added to
+ it.
+ \value Reset The entire query has been reset from the beginning. Any previous
+ monitoring is now invalid.
+*/
+
+/*!
+ Run the script in \a context and return the result. \a voidCache should
+ contain state memory previously acquired from newScript.
+ */
+QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *cached)
+{
+ if (!isValid())
+ return QVariant();
+
+ QmlBasicScriptNodeCache *dataCache =
+ reinterpret_cast<QmlBasicScriptNodeCache *>(voidCache);
+ int dataCacheItem;
+ QStack<QVariant> stack;
+
+ bool resetting = false;
+ bool hasReset = false;
+
+ const char *data = d->data();
+
+ if (dataCache[0].type == QmlBasicScriptNodeCache::Invalid) {
+ resetting = true;
+ hasReset = true;
+ }
+
+ CacheState state = NoChange;
+
+ dataCacheItem = 0;
+ for (int idx = 0; idx < d->instructionCount; ++idx) {
+ const ScriptInstruction &instr = d->instructions()[idx];
+
+ switch(instr.type) {
+ case ScriptInstruction::Load: // either an object or a property
+ case ScriptInstruction::Fetch: // can only be a property
+ {
+ const char *id = data + instr.fetch.idx;
+ QmlBasicScriptNodeCache &n = dataCache[dataCacheItem];
+
+ if (instr.type == ScriptInstruction::Load) {
+
+ if (n.type == QmlBasicScriptNodeCache::Invalid) {
+ context->engine()->d_func()->loadCache(n, QLatin1String(id), static_cast<QmlContextPrivate*>(context->d_ptr));
+ state = Incremental;
+ }
+
+ if(!n.isValid())
+ qWarning("ReferenceError: %s is not defined", id);
+
+ } else { // instr.type == ScriptInstruction::Fetch
+
+ QVariant o = stack.pop();
+ QObject *obj = qvariant_cast<QObject *>(o);
+ if (!obj) {
+ if (n.type == QmlBasicScriptNodeCache::Invalid) {
+ if (scriptWarnings())
+ qWarning() << "QmlBasicScript: Unable to convert" << o;
+ *cached = state;
+ return QVariant();
+ } else {
+ clearCache(dataCache);
+ *cached = Reset;
+ CacheState dummy;
+ return run(context, voidCache, &dummy);
+ }
+ } else if (n.type == QmlBasicScriptNodeCache::Invalid) {
+ context->engine()->d_func()->fetchCache(n, QLatin1String(id), obj);
+ guard(n);
+ state = Incremental;
+ } else if (!valid(n, obj)) {
+ clearCache(dataCache);
+ *cached = Reset;
+ CacheState dummy;
+ return run(context, voidCache, &dummy);
+ }
+
+ }
+
+ QVariant var = n.value(id);
+ stack.push(var);
+ ++dataCacheItem;
+ }
+ break;
+ case ScriptInstruction::Int:
+ stack.push(QVariant(instr.integer.value));
+ break;
+ case ScriptInstruction::Bool:
+ stack.push(QVariant(instr.boolean.value));
+ break;
+ case ScriptInstruction::Add:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs.toDouble() + lhs.toDouble());
+ }
+ break;
+ case ScriptInstruction::Subtract:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(lhs.toDouble() - rhs.toDouble());
+ }
+ break;
+ case ScriptInstruction::Multiply:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs.toDouble() * lhs.toDouble());
+ }
+ break;
+ case ScriptInstruction::Equals:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs == lhs);
+ }
+ break;
+ case ScriptInstruction::And:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs.toBool() && lhs.toBool());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ *cached = state;
+
+ if (stack.isEmpty())
+ return QVariant();
+ else
+ return stack.top();
+}
+
+/*!
+ Return a pointer to the script's compile data, or null if there is no data.
+ */
+const char *QmlBasicScript::compileData() const
+{
+ return (const char *)d;
+}
+
+/*!
+ Return the size of the script's compile data, or zero if there is no data.
+ The size will always be a multiple of 4.
+ */
+unsigned int QmlBasicScript::compileDataSize() const
+{
+ if (d)
+ return d->size;
+ else
+ return 0;
+}
+
+bool QmlBasicScript::isSingleLoad() const
+{
+ if (!d)
+ return false;
+
+ return d->instructionCount == 1 &&
+ d->instructions()[0].type == ScriptInstruction::Load;
+}
+
+QByteArray QmlBasicScript::singleLoadTarget() const
+{
+ if (!isSingleLoad())
+ return QByteArray();
+
+ // We know there is one instruction and it is a load
+ return QByteArray(d->data() + d->instructions()[0].fetch.idx);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/script/qmlbasicscript.h b/src/declarative/qml/script/qmlbasicscript.h
new file mode 100644
index 0000000..d465f04
--- /dev/null
+++ b/src/declarative/qml/script/qmlbasicscript.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBASICSCRIPT_H
+#define QMLBASICSCRIPT_H
+
+#include "instructions.h"
+#include <QList>
+#include <QByteArray>
+#include "lexer.h"
+#include <QVariant>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlRefCount;
+class QmlContext;
+class QmlBasicScriptPrivate;
+class QmlBasicScriptNodeCache;
+class QmlBasicScript
+{
+public:
+ QmlBasicScript();
+ QmlBasicScript(const char *, QmlRefCount * = 0);
+ ~QmlBasicScript();
+
+ // Always 4-byte aligned
+ const char *compileData() const;
+ unsigned int compileDataSize() const;
+
+ QByteArray expression() const;
+
+ bool compile(const QByteArray &);
+ bool compile(const char *);
+ bool isValid() const;
+
+ void clear();
+
+ void dump();
+ void *newScriptState();
+ void deleteScriptState(void *);
+
+ enum CacheState { NoChange, Incremental, Reset };
+ QVariant run(QmlContext *, void *, CacheState *);
+
+ // Optimization opportunities
+ bool isSingleLoad() const;
+ QByteArray singleLoadTarget() const;
+
+private:
+ int flags;
+ QmlBasicScriptPrivate *d;
+ QmlRefCount *rc;
+
+ void clearCache(void *);
+ void guard(QmlBasicScriptNodeCache &);
+ bool valid(QmlBasicScriptNodeCache &, QObject *);
+};
+
+#endif // QMLBASICSCRIPT_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/qml/script/qmlbasicscript_p.h b/src/declarative/qml/script/qmlbasicscript_p.h
new file mode 100644
index 0000000..3b7e966
--- /dev/null
+++ b/src/declarative/qml/script/qmlbasicscript_p.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBASICSCRIPT_P_H
+#define QMLBASICSCRIPT_P_H
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QmlContextPrivate;
+class QDebug;
+class QByteArray;
+
+class QmlBasicScriptNodeCache
+{
+public:
+ QObject *object;
+ const QMetaObject *metaObject;
+ enum { Invalid,
+ Core,
+ Attached,
+ Signal,
+ SignalProperty,
+ Variant
+ } type;
+ union {
+ int core;
+ QObject *attached;
+ QmlContextPrivate *context;
+ };
+ int coreType;
+ int contextIndex;
+
+ bool isValid() const { return type != Invalid; }
+ bool isCore() const { return type == Core; }
+ bool isVariant() const { return type == Variant; }
+ void clear();
+ QVariant value(const char *) const;
+};
+
+QDebug operator<<(QDebug, const QmlBasicScriptNodeCache &);
+
+#endif // QMLBASICSCRIPT_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/script/script.pri b/src/declarative/qml/script/script.pri
new file mode 100644
index 0000000..6c43efe
--- /dev/null
+++ b/src/declarative/qml/script/script.pri
@@ -0,0 +1,11 @@
+SOURCES += \
+ qml/script/tokens.cpp \
+ qml/script/lexer.cpp \
+ qml/script/qmlbasicscript.cpp
+
+HEADERS += \
+ qml/script/tokens.h \
+ qml/script/lexer.h \
+ qml/script/instructions.h \
+ qml/script/qmlbasicscript.h \
+ qml/script/qmlbasicscript_p.h
diff --git a/src/declarative/qml/script/tokens.cpp b/src/declarative/qml/script/tokens.cpp
new file mode 100644
index 0000000..a2fb100
--- /dev/null
+++ b/src/declarative/qml/script/tokens.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "tokens.h"
+
+
+/*!
+ Returns a string representation of token \a tok.
+*/
+const char *tokenToString(Token tok)
+{
+ switch(tok) {
+#define CASE(X) case X: return #X;
+ CASE(NOTOKEN)
+ CASE(INCOMPLETE)
+ CASE(WHITESPACE)
+ CASE(LANGLE)
+ CASE(RANGLE)
+ CASE(PLUS)
+ CASE(MINUS)
+ CASE(STAR)
+ CASE(EQUALS)
+ CASE(DOT)
+ CASE(CHARACTER)
+ CASE(DIGIT)
+ CASE(OTHER)
+ CASE(AND)
+ case TOKEN_TRUE:
+ return "TRUE";
+ case TOKEN_FALSE:
+ return "FALSE";
+#undef CASE
+ }
+ return 0;
+}
+
diff --git a/src/declarative/qml/script/tokens.h b/src/declarative/qml/script/tokens.h
new file mode 100644
index 0000000..753e40c
--- /dev/null
+++ b/src/declarative/qml/script/tokens.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOKENS_H
+#define TOKENS_H
+
+enum Token {
+ // Lexer tokens
+ NOTOKEN,
+ INCOMPLETE,
+ WHITESPACE,
+ LANGLE,
+ RANGLE,
+ PLUS,
+ MINUS,
+ STAR,
+ EQUALS,
+ AND,
+ DOT,
+ CHARACTER,
+ DIGIT,
+ TOKEN_TRUE,
+ TOKEN_FALSE,
+ OTHER
+};
+
+const char *tokenToString(Token);
+
+#endif
diff --git a/src/declarative/test/qfxtestengine.cpp b/src/declarative/test/qfxtestengine.cpp
new file mode 100644
index 0000000..70e600d
--- /dev/null
+++ b/src/declarative/test/qfxtestengine.cpp
@@ -0,0 +1,457 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QFile>
+#include <QmlComponent>
+#include <qmltimeline.h>
+#include "qfxtestengine.h"
+#include "qfxtestobjects.h"
+#include <QCryptographicHash>
+#include <QApplication>
+#include <QKeyEvent>
+#include <QSimpleCanvas>
+#include <QMouseEvent>
+#include <qmlengine.h>
+#include <private/qabstractanimation_p.h>
+#include <QAbstractAnimation>
+
+QT_BEGIN_NAMESPACE
+
+#define MAX_MISMATCHED_FRAMES 5
+#define MAX_MISMATCHED_PIXELS 5
+
+class QFxTestEnginePrivate : public QAbstractAnimation
+{
+public:
+ QFxTestEnginePrivate(QFxTestEngine *p)
+ : q(p), canvas(0), testMode(QFxTestEngine::NoTest), fullFrame(true),
+ status(Working), exitOnFail(true), mismatchedFrames(0),
+ lastFrameMismatch(false) {}
+
+ QFxTestEngine *q;
+
+ QmlEngine engine;
+ QSimpleCanvas *canvas;
+ QFxTestEngine::TestMode testMode;
+ QString testDirectory;
+
+ TestLog testData;
+ TestLog playbackTestData;
+ bool fullFrame;
+ QList<QImage> fullFrames;
+
+ virtual void updateCurrentTime(int);
+
+ void recordFrameEvent(const QImage &img);
+ void recordFullFrameEvent(const QImage &img);
+ void recordKeyEvent(QKeyEvent *e);
+ void recordMouseEvent(QMouseEvent *e);
+ void testPass();
+ void save(const QString &filename, bool = true);
+
+ enum MessageType { Success, Fail };
+ void message(MessageType t, const char *);
+
+ enum Status { Working, Failed, Passed };
+ Status status;
+ bool exitOnFail;
+
+ QList<TestObject *> toPost;
+ QSet<QEvent *> postedEvents;
+
+ // OpenGL seems to give inconsistent rendering results. We allow a small
+ // tolerance to compensate - a maximum number of mismatched frames and only
+ // one mismatch in a row
+ int mismatchedFrames;
+ bool lastFrameMismatch;
+
+ bool compare(const QImage &img1, const QImage &img2);
+
+ virtual int duration() const { return -1; }
+};
+
+bool QFxTestEnginePrivate::compare(const QImage &img1, const QImage &img2)
+{
+ if (img1.size() != img2.size())
+ return false;
+
+ int errorCount = 0;
+ for (int yy = 0; yy < img1.height(); ++yy) {
+ for (int xx = 0; xx < img1.width(); ++xx) {
+ if (img1.pixel(xx, yy) != img2.pixel(xx, yy)) {
+ errorCount++;
+ if (errorCount > MAX_MISMATCHED_PIXELS)
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+QFxTestEngine::QFxTestEngine(TestMode mode, const QString &dir,
+ QSimpleCanvas *canvas, QObject *parent)
+: QObject(parent), d(new QFxTestEnginePrivate(this))
+{
+ Q_ASSERT(canvas);
+
+ d->canvas = canvas;
+ d->start();
+
+ d->testDirectory = dir;
+ d->testMode = mode;
+ if (d->testMode == RecordTest) {
+ qWarning("QFxTestEngine: Record ON");
+ } else if (d->testMode == PlaybackTest) {
+
+ QString fileName(d->testDirectory + QLatin1String("/manifest.xml"));
+ QFile f(fileName);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning() << "QFxTestEngine: Unable to open file" << fileName;
+ return;
+ }
+
+ QByteArray data = f.readAll();
+ QmlComponent c(&d->engine, data, QUrl(d->testDirectory + QLatin1String("/manifest.xml")));
+ QObject *o = c.create();
+ TestLog *log = qobject_cast<TestLog *>(o);
+ if (log) {
+ log->setParent(this);
+ d->playbackTestData.actions() = log->actions();
+ qWarning("QFxTestEngine: Playback ON");
+ } else {
+ delete o;
+ qWarning() << "QFxTestEngine: File" << fileName << "is corrupt.";
+ return;
+ }
+ }
+
+ if (d->testMode != NoTest) {
+
+ QUnifiedTimer::instance()->setConsistentTiming(true);
+ QObject::connect(canvas, SIGNAL(framePainted()),
+ this, SLOT(framePainted()));
+
+ canvas->installEventFilter(this);
+ for (int ii = 0; ii < d->playbackTestData.actions().count(); ++ii) {
+ TestObject *o = d->playbackTestData.actions().at(ii);
+ if (TestMouse *m = qobject_cast<TestMouse *>(o))
+ d->toPost << m;
+ else if (TestKey *k = qobject_cast<TestKey *>(o))
+ d->toPost << k;
+ }
+ }
+}
+
+QFxTestEngine::~QFxTestEngine()
+{
+ delete d; d = 0;
+}
+
+void QFxTestEngine::framePainted()
+{
+ QImage img = d->canvas->asImage();
+
+ if (d->fullFrame) {
+ d->fullFrame = false;
+ d->recordFullFrameEvent(img);
+ } else {
+ d->recordFrameEvent(img);
+ }
+}
+
+void QFxTestEnginePrivate::recordFullFrameEvent(const QImage &img)
+{
+ TestFullFrame *ff = new TestFullFrame(q);
+ ff->setTime(QUnifiedTimer::instance()->elapsedTime());
+ ff->setFrameId(fullFrames.count());
+
+ fullFrames << img;
+ testData.actions() << ff;
+
+ if (testMode == QFxTestEngine::PlaybackTest) {
+ TestFullFrame *pf = qobject_cast<TestFullFrame *>(playbackTestData.next());
+ QString filename = testDirectory + QLatin1String("/image") + QString::number(pf->frameId()) + QLatin1String(".png");
+ QImage recImg(filename);
+ if (!pf || !compare(recImg, img) || pf->time() != QUnifiedTimer::instance()->elapsedTime()) {
+ message(Fail, "FFrame mismatch");
+ } else {
+ message(Success, "FFrame OK");
+ }
+
+ testPass();
+ }
+}
+
+static QByteArray toHex(uchar c)
+{
+ QByteArray rv;
+ uint h = c / 16;
+ uint l = c % 16;
+ if (h >= 10)
+ rv.append(h - 10 + 'A');
+ else
+ rv.append(h + '0');
+ if (l >= 10)
+ rv.append(l - 10 + 'A');
+ else
+ rv.append(l + '0');
+ return rv;
+}
+
+void QFxTestEnginePrivate::recordFrameEvent(const QImage &img)
+{
+ QCryptographicHash hash(QCryptographicHash::Md5);
+
+ hash.addData((const char *)img.bits(), img.bytesPerLine() * img.height());
+
+ QByteArray result = hash.result();
+ QByteArray hexResult;
+ for (int ii = 0; ii < result.count(); ++ii)
+ hexResult.append(toHex(result.at(ii)));
+
+ TestFrame *f = new TestFrame(q);
+ f->setTime(QUnifiedTimer::instance()->elapsedTime());
+
+ f->setHash(QLatin1String(hexResult));
+ testData.actions() << f;
+ if (testMode == QFxTestEngine::PlaybackTest) {
+ TestObject *o = playbackTestData.next();
+ TestFrame *f = qobject_cast<TestFrame *>(o);
+ if (!f || f->time() != QUnifiedTimer::instance()->elapsedTime() ||
+ f->hash() != QLatin1String(hexResult)) {
+ mismatchedFrames++;
+ if (mismatchedFrames > MAX_MISMATCHED_FRAMES ||
+ lastFrameMismatch)
+ message(Fail, "Frame mismatch");
+ else
+ message(Success, "Frame mismatch - within tolerance");
+ lastFrameMismatch = true;
+ } else {
+ message(Success, "Frame OK");
+ lastFrameMismatch = false;
+ }
+
+ testPass();
+ }
+}
+
+void QFxTestEnginePrivate::updateCurrentTime(int)
+{
+ if (status != Working)
+ return;
+
+ while(!toPost.isEmpty()) {
+ int t = QUnifiedTimer::instance()->elapsedTime();
+ TestObject *o = toPost.first();
+ if (testMode == QFxTestEngine::RecordTest)
+ o->setTime(t);
+ else if (o->time() != t)
+ return;
+ toPost.takeFirst();
+
+ if (TestMouse *m = qobject_cast<TestMouse *>(o)) {
+ QMouseEvent e((QEvent::Type)m->type(), m->pos(), m->globalPos(), (Qt::MouseButton)m->button(), (Qt::MouseButtons)m->buttons(), (Qt::KeyboardModifiers)0);
+ postedEvents.insert(&e);
+ QApplication::sendEvent(canvas, &e);
+ } else if (TestKey *k = qobject_cast<TestKey *>(o)) {
+ QKeyEvent e((QEvent::Type)k->type(), k->key(), (Qt::KeyboardModifiers)k->modifiers(), k->text());
+ postedEvents.insert(&e);
+ QApplication::sendEvent(canvas, &e);
+ }
+ }
+}
+
+bool QFxTestEngine::eventFilter(QObject *, QEvent *event)
+{
+ if (d->status != QFxTestEnginePrivate::Working)
+ return false;
+
+ if (event->type() == QEvent::MouseButtonPress ||
+ event->type() == QEvent::MouseButtonDblClick ||
+ event->type() == QEvent::MouseButtonRelease ||
+ event->type() == QEvent::MouseMove) {
+ if (d->testMode == RecordTest && d->postedEvents.contains(event)) {
+ d->postedEvents.remove(event);
+ } else {
+ d->recordMouseEvent(static_cast<QMouseEvent *>(event));
+ return d->testMode == RecordTest;
+ }
+ } else if (event->type() == QEvent::KeyPress ||
+ event->type() == QEvent::KeyRelease) {
+ QKeyEvent *key = static_cast<QKeyEvent *>(event);
+ if (key->key() < Qt::Key_F1 || key->key() > Qt::Key_F9) {
+
+ if (d->testMode == RecordTest && d->postedEvents.contains(event)) {
+ d->postedEvents.remove(event);
+ } else {
+ d->recordKeyEvent(key);
+ return d->testMode == RecordTest;
+ }
+
+ }
+ }
+
+ return false;
+}
+
+void QFxTestEnginePrivate::recordMouseEvent(QMouseEvent *e)
+{
+ TestMouse *m = new TestMouse(q);
+ m->setTime(QUnifiedTimer::instance()->elapsedTime());
+ m->setType(e->type());
+ m->setButton(e->button());
+ m->setButtons(e->buttons());
+ m->setGlobalPos(e->globalPos());
+ m->setPos(e->pos());
+ testData.actions() << m;
+
+ if (testMode == QFxTestEngine::PlaybackTest) {
+ TestMouse *m = qobject_cast<TestMouse *>(playbackTestData.next());
+ if (!m || m->time() != QUnifiedTimer::instance()->elapsedTime() ||
+ m->type() != e->type() ||
+ m->button() != e->button() ||
+ m->buttons() != e->buttons() ||
+ m->globalPos() != e->globalPos() ||
+ m->pos() != e->pos())
+ message(Fail, "Mouse mismatch");
+ else
+ message(Success, "Mouse OK");
+
+ testPass();
+ } else {
+ toPost << m;
+ }
+
+}
+
+void QFxTestEnginePrivate::recordKeyEvent(QKeyEvent *e)
+{
+ TestKey *k = new TestKey(q);
+ k->setTime(QUnifiedTimer::instance()->elapsedTime());
+ k->setType(e->type());
+ k->setModifiers(e->QInputEvent::modifiers());
+ k->setText(e->text());
+ k->setKey(e->key());
+ testData.actions() << k;
+ if (testMode == QFxTestEngine::PlaybackTest) {
+ TestKey *f = qobject_cast<TestKey *>(playbackTestData.next());
+ if (!f || f->time() != QUnifiedTimer::instance()->elapsedTime() ||
+ f->type() != e->type() ||
+ f->modifiers() != e->QInputEvent::modifiers() ||
+ f->text() != e->text() ||
+ f->key() != e->key())
+ message(Fail, "Key mismatch");
+ else
+ message(Success, "Key OK");
+
+ testPass();
+ } else {
+ toPost << k;
+ }
+}
+
+void QFxTestEngine::captureFullFrame()
+{
+ d->fullFrame = true;
+}
+
+void QFxTestEnginePrivate::message(MessageType t, const char *message)
+{
+ if (exitOnFail)
+ qWarning("%s", message);
+ if (t == Fail) {
+ if (exitOnFail) {
+ save(QLatin1String("manifest-fail.xml"), false);
+ qFatal("Failed");
+ } else {
+ status = Failed;
+ }
+ }
+}
+
+void QFxTestEnginePrivate::save(const QString &filename, bool images)
+{
+ qWarning() << "QFxTestEngine: Writing test data";
+
+ QFile manifest(testDirectory + QLatin1String("/") + filename);
+ manifest.open(QIODevice::WriteOnly);
+ testData.save(&manifest);
+ manifest.close();
+
+ if (images) {
+ for (int ii = 0; ii < fullFrames.count(); ++ii)
+ fullFrames.at(ii).save(testDirectory + QLatin1String("/image") + QString::number(ii) + QLatin1String(".png"));
+ }
+}
+
+void QFxTestEngine::save()
+{
+ if (d->testMode != RecordTest)
+ return;
+
+ d->save(QLatin1String("manifest.xml"));
+}
+
+void QFxTestEnginePrivate::testPass()
+{
+ if (playbackTestData.atEnd()) {
+ qWarning("Test PASSED");
+ if (exitOnFail) {
+ save(QLatin1String("manifest-play.xml"));
+ exit(0);
+ } else {
+ status = Passed;
+ }
+ }
+}
+
+bool QFxTestEngine::runTest()
+{
+ d->exitOnFail = false;
+ while(d->status == QFxTestEnginePrivate::Working)
+ QApplication::processEvents();
+ d->exitOnFail = true;
+ qWarning() << d->status;
+ return d->status == QFxTestEnginePrivate::Passed;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/test/qfxtestengine.h b/src/declarative/test/qfxtestengine.h
new file mode 100644
index 0000000..6698645
--- /dev/null
+++ b/src/declarative/test/qfxtestengine.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QFXTESTENGINE_H_
+#define _QFXTESTENGINE_H_
+
+#include <QObject>
+class QSimpleCanvas;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QFxTestEnginePrivate;
+class Q_DECLARATIVE_EXPORT QFxTestEngine : public QObject
+{
+Q_OBJECT
+public:
+ enum TestMode { NoTest, RecordTest, PlaybackTest };
+
+ QFxTestEngine(TestMode, const QString &,
+ QSimpleCanvas *canvas, QObject * = 0);
+ virtual ~QFxTestEngine();
+
+ void captureFullFrame();
+ void save();
+
+ bool runTest();
+
+protected:
+ virtual bool eventFilter(QObject *, QEvent *);
+
+private Q_SLOTS:
+ void framePainted();
+
+private:
+ QFxTestEnginePrivate *d;
+};
+
+#endif // _QFXTESTENGINE_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/test/qfxtestobjects.cpp b/src/declarative/test/qfxtestobjects.cpp
new file mode 100644
index 0000000..be1ab07
--- /dev/null
+++ b/src/declarative/test/qfxtestobjects.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qfxtestobjects.h"
+#include <qml.h>
+#include <QIODevice>
+
+
+QT_BEGIN_NAMESPACE
+QML_DECLARE_TYPE(TestObject);
+QML_DEFINE_TYPE(TestObject,TestObject);
+QML_DECLARE_TYPE(TestFrame);
+QML_DEFINE_TYPE(TestFrame,TestFrame);
+QML_DECLARE_TYPE(TestFullFrame);
+QML_DEFINE_TYPE(TestFullFrame,TestFullFrame);
+QML_DECLARE_TYPE(TestMouse);
+QML_DEFINE_TYPE(TestMouse,TestMouse);
+QML_DECLARE_TYPE(TestKey);
+QML_DEFINE_TYPE(TestKey,TestKey);
+QML_DECLARE_TYPE(TestLog);
+QML_DEFINE_TYPE(TestLog,TestLog);
+
+TestObject::TestObject(QObject *parent)
+: QObject(parent), _time(-1)
+{
+}
+
+int TestObject::time() const
+{
+ return _time;
+}
+
+void TestObject::setTime(int t)
+{
+ if (t == _time)
+ return;
+ _time = t;
+ emit dataChanged();
+}
+
+void TestObject::save(QXmlStreamWriter *device)
+{
+ device->writeStartElement(QLatin1String("TestObject"));
+ device->writeAttribute(QLatin1String("time"), QString::number(time()));
+ device->writeEndElement();
+}
+
+
+TestFrame::TestFrame(QObject *parent)
+: TestObject(parent)
+{
+}
+
+QString TestFrame::hash() const
+{
+ return _hash;
+}
+
+void TestFrame::setHash(const QString &h)
+{
+ if (_hash == h)
+ return;
+ _hash = h;
+ emit frameChanged();
+}
+
+void TestFrame::save(QXmlStreamWriter *device)
+{
+ device->writeStartElement(QLatin1String("TestFrame"));
+ device->writeAttribute(QLatin1String("time"), QLatin1String(QByteArray::number(time())));
+ device->writeAttribute(QLatin1String("hash"), hash());
+ device->writeEndElement();
+}
+
+TestFullFrame::TestFullFrame(QObject *parent)
+: TestObject(parent), _frameId(-1)
+{
+}
+
+int TestFullFrame::frameId() const
+{
+ return _frameId;
+}
+
+void TestFullFrame::setFrameId(int id)
+{
+ if (id == _frameId)
+ return;
+ _frameId = id;
+ emit frameChanged();
+}
+
+void TestFullFrame::save(QXmlStreamWriter *device)
+{
+ device->writeStartElement(QLatin1String("TestFullFrame"));
+ device->writeAttribute(QLatin1String("time"), QLatin1String(QByteArray::number(time())));
+ device->writeAttribute(QLatin1String("frameId"), QLatin1String(QByteArray::number(frameId())));
+ device->writeEndElement();
+}
+
+TestMouse::TestMouse(QObject *parent)
+: TestObject(parent), _type(-1), _button(-1), _buttons(-1)
+{
+}
+
+int TestMouse::type() const
+{
+ return _type;
+}
+
+void TestMouse::setType(int t)
+{
+ if (_type == t)
+ return;
+ _type = t;
+ emit mouseChanged();
+}
+
+int TestMouse::button() const
+{
+ return _button;
+}
+
+void TestMouse::setButton(int b)
+{
+ if (b == _button)
+ return;
+ _button = b;
+ emit mouseChanged();
+}
+
+int TestMouse::buttons() const
+{
+ return _buttons;
+}
+
+void TestMouse::setButtons(int buttons)
+{
+ if (_buttons == buttons)
+ return;
+ _buttons = buttons;
+ emit mouseChanged();
+}
+
+QPoint TestMouse::globalPos() const
+{
+ return _globalPos;
+}
+
+void TestMouse::setGlobalPos(const QPoint &g)
+{
+ if (_globalPos == g)
+ return;
+ _globalPos = g;
+ emit mouseChanged();
+}
+
+QPoint TestMouse::pos() const
+{
+ return _pos;
+}
+
+void TestMouse::setPos(const QPoint &p)
+{
+ if (p == _pos)
+ return;
+ _pos = p;
+ emit mouseChanged();
+}
+
+void TestMouse::save(QXmlStreamWriter *device)
+{
+ device->writeStartElement(QLatin1String("TestMouse"));
+ device->writeAttribute(QLatin1String("time"), QString::number(time()));
+ device->writeAttribute(QLatin1String("type"), QString::number(type()));
+ device->writeAttribute(QLatin1String("button"), QString::number(button()));
+ device->writeAttribute(QLatin1String("buttons"), QString::number(buttons()));
+ device->writeAttribute(QLatin1String("globalPos"), QString::number(globalPos().x()) + QLatin1String(",") + QString::number(globalPos().y()));
+ device->writeAttribute(QLatin1String("pos"), QString::number(pos().x()) + QLatin1String(",") + QString::number(pos().y()));
+ device->writeEndElement();
+}
+
+TestKey::TestKey(QObject *parent)
+: TestObject(parent), _type(-1), _modifiers(-1), _key(-1)
+{
+}
+
+int TestKey::type() const
+{
+ return _type;
+}
+
+void TestKey::setType(int t)
+{
+ if (t == _type)
+ return;
+ _type = t;
+ emit keyChanged();
+}
+
+int TestKey::modifiers() const
+{
+ return _modifiers;
+}
+
+void TestKey::setModifiers(int m)
+{
+ if (m == _modifiers)
+ return;
+ _modifiers = m;
+ emit keyChanged();
+}
+
+QString TestKey::text() const
+{
+ return _text;
+}
+
+void TestKey::setText(const QString &t)
+{
+ if (_text == t)
+ return;
+ _text = t;
+ emit keyChanged();
+}
+
+int TestKey::key() const
+{
+ return _key;
+}
+
+void TestKey::setKey(int k)
+{
+ if (_key == k)
+ return;
+ _key = k;
+ emit keyChanged();
+}
+
+void TestKey::save(QXmlStreamWriter *device)
+{
+ device->writeStartElement(QLatin1String("TestKey"));
+ device->writeAttribute(QLatin1String("time"), QString::number(time()));
+ device->writeAttribute(QLatin1String("type"), QString::number(type()));
+ device->writeAttribute(QLatin1String("modifiers"), QString::number(modifiers()));
+ device->writeAttribute(QLatin1String("key"), QString::number(key()));
+ if (key() != Qt::Key_Escape)
+ device->writeAttribute(QLatin1String("text"), text());
+ device->writeEndElement();
+}
+
+TestLog::TestLog(QObject *parent)
+: QObject(parent), _current(0)
+{
+}
+
+QList<TestObject *> *TestLog::qmlActions()
+{
+ return &_actions;
+}
+
+QList<TestObject *> &TestLog::actions()
+{
+ return _actions;
+}
+
+bool lessThan(TestObject *lhs, TestObject *rhs)
+{
+ return lhs->time() < rhs->time();
+}
+
+void TestLog::save(QIODevice *device)
+{
+ // Order correctly
+ qStableSort(_actions.begin(), _actions.end(), lessThan);
+
+ QXmlStreamWriter writer(device);
+ writer.setAutoFormatting(true);
+ writer.writeStartDocument(QLatin1String("1.0"));
+ writer.writeStartElement(QLatin1String("TestLog"));
+ for (int ii = 0; ii < _actions.count(); ++ii)
+ _actions.at(ii)->save(&writer);
+ writer.writeEndElement();
+ writer.writeEndDocument();
+}
+
+TestObject *TestLog::next()
+{
+ if (atEnd())
+ return 0;
+ TestObject *rv = _actions.at(_current);
+ _current++;
+ return rv;
+}
+
+bool TestLog::atEnd() const
+{
+ if (_current >= _actions.count())
+ return true;
+ else
+ return false;
+}
+
+int TestLog::current() const
+{
+ return _current;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/test/qfxtestobjects.h b/src/declarative/test/qfxtestobjects.h
new file mode 100644
index 0000000..4273d4e
--- /dev/null
+++ b/src/declarative/test/qfxtestobjects.h
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QFXTESTOBJECTS_H_
+#define _QFXTESTOBJECTS_H_
+
+#include <QObject>
+#include <QPoint>
+#include <QList>
+#include <QXmlStreamWriter>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QIODevice;
+class TestObject : public QObject
+{
+Q_OBJECT
+public:
+ TestObject(QObject * = 0);
+
+ Q_PROPERTY(int time READ time WRITE setTime NOTIFY dataChanged);
+ int time() const;
+ void setTime(int);
+
+ virtual void save(QXmlStreamWriter *);
+Q_SIGNALS:
+ void dataChanged();
+
+private:
+ int _time;
+};
+
+class TestFrame : public TestObject
+{
+Q_OBJECT
+public:
+ TestFrame(QObject * = 0);
+
+ Q_PROPERTY(QString hash READ hash WRITE setHash NOTIFY frameChanged);
+ QString hash() const;
+ void setHash(const QString &);
+
+ virtual void save(QXmlStreamWriter *);
+Q_SIGNALS:
+ void frameChanged();
+
+private:
+ QString _hash;
+};
+
+class TestFullFrame : public TestObject
+{
+Q_OBJECT
+public:
+ TestFullFrame(QObject * = 0);
+
+ Q_PROPERTY(int frameId READ frameId WRITE setFrameId NOTIFY frameChanged);
+ int frameId() const;
+ void setFrameId(int);
+
+ virtual void save(QXmlStreamWriter *);
+Q_SIGNALS:
+ void frameChanged();
+
+private:
+ int _frameId;
+};
+
+class TestMouse : public TestObject
+{
+Q_OBJECT
+public:
+ TestMouse(QObject * = 0);
+
+ Q_PROPERTY(int type READ type WRITE setType NOTIFY mouseChanged);
+ int type() const;
+ void setType(int);
+
+ Q_PROPERTY(int button READ button WRITE setButton NOTIFY mouseChanged);
+ int button() const;
+ void setButton(int);
+
+ Q_PROPERTY(int buttons READ buttons WRITE setButtons NOTIFY mouseChanged);
+ int buttons() const;
+ void setButtons(int);
+
+ Q_PROPERTY(QPoint globalPos READ globalPos WRITE setGlobalPos NOTIFY mouseChanged);
+ QPoint globalPos() const;
+ void setGlobalPos(const QPoint &);
+
+ Q_PROPERTY(QPoint pos READ pos WRITE setPos NOTIFY mouseChanged);
+ QPoint pos() const;
+ void setPos(const QPoint &);
+
+ virtual void save(QXmlStreamWriter *);
+
+Q_SIGNALS:
+ void mouseChanged();
+
+private:
+ int _type;
+ int _button;
+ int _buttons;
+ QPoint _globalPos;
+ QPoint _pos;
+};
+
+class TestKey : public TestObject
+{
+Q_OBJECT
+public:
+ TestKey(QObject * = 0);
+
+ Q_PROPERTY(int type READ type WRITE setType NOTIFY keyChanged);
+ int type() const;
+ void setType(int);
+
+ Q_PROPERTY(int modifiers READ modifiers WRITE setModifiers NOTIFY keyChanged);
+ int modifiers() const;
+ void setModifiers(int);
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY keyChanged);
+ QString text() const;
+ void setText(const QString &);
+
+ Q_PROPERTY(int key READ key WRITE setKey NOTIFY keyChanged);
+ int key() const;
+ void setKey(int);
+
+ virtual void save(QXmlStreamWriter *);
+
+Q_SIGNALS:
+ void keyChanged();
+
+private:
+ int _type;
+ int _modifiers;
+ int _key;
+ QString _text;
+};
+
+class TestLog : public QObject
+{
+Q_OBJECT
+public:
+ TestLog(QObject * = 0);
+
+ Q_CLASSINFO("DefaultProperty", "actions");
+ Q_PROPERTY(QList<TestObject *> *actions READ qmlActions);
+ QList<TestObject *> *qmlActions();
+
+ QList<TestObject *> &actions();
+
+ int current() const;
+ void save(QIODevice *);
+
+ TestObject *next();
+ bool atEnd() const;
+
+private:
+ int _current;
+ QList<TestObject *> _actions;
+};
+
+#endif // _QFXTESTOBJECTS_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/test/qfxtestview.cpp b/src/declarative/test/qfxtestview.cpp
new file mode 100644
index 0000000..94bcb30
--- /dev/null
+++ b/src/declarative/test/qfxtestview.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxtestview.h"
+#include <QFile>
+#include <QmlComponent>
+#include <QFileInfo>
+#include <QFxItem>
+#include <QmlContext>
+#include <QFxTestEngine>
+
+
+QT_BEGIN_NAMESPACE
+QFxTestView::QFxTestView(const QString &filename, const QString &testdir)
+: testEngine(0)
+{
+ QObject::connect(this, SIGNAL(sceneResized(QSize)),
+ this, SLOT(setSceneSize(QSize)));
+
+ testEngine = new QFxTestEngine(QFxTestEngine::PlaybackTest, testdir, this, this);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString qml = QString::fromUtf8(file.readAll());
+ setQml(qml, filename);
+
+ execute();
+}
+
+void QFxTestView::setSceneSize(QSize s)
+{
+ setFixedSize(s);
+}
+
+bool QFxTestView::runTest()
+{
+ show();
+ return testEngine->runTest();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/test/qfxtestview.h b/src/declarative/test/qfxtestview.h
new file mode 100644
index 0000000..33275b9
--- /dev/null
+++ b/src/declarative/test/qfxtestview.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _QFXTESTVIEW_H_
+#define _QFXTESTVIEW_H_
+
+#include <QFxView>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QFxTestEngine;
+class Q_DECLARATIVE_EXPORT QFxTestView : public QFxView
+{
+Q_OBJECT
+public:
+ QFxTestView(const QString &filename, const QString &testdir);
+
+ bool runTest();
+
+private Q_SLOTS:
+ void setSceneSize(QSize);
+
+private:
+ QFxTestEngine *testEngine;
+};
+
+#endif // _QFXTESTVIEW_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/test/test.pri b/src/declarative/test/test.pri
new file mode 100644
index 0000000..eacd00f
--- /dev/null
+++ b/src/declarative/test/test.pri
@@ -0,0 +1,9 @@
+SOURCES += \
+ test/qfxtestengine.cpp \
+ test/qfxtestobjects.cpp \
+ test/qfxtestview.cpp
+
+HEADERS += \
+ test/qfxtestengine.h \
+ test/qfxtestobjects.h \
+ test/qfxtestview.h
diff --git a/src/declarative/timeline/qmltimeline.cpp b/src/declarative/timeline/qmltimeline.cpp
new file mode 100644
index 0000000..dcc8745
--- /dev/null
+++ b/src/declarative/timeline/qmltimeline.cpp
@@ -0,0 +1,940 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltimeline.h"
+#include <QDebug>
+#include <QMutex>
+#include <QThread>
+#include <QWaitCondition>
+#include <QEvent>
+#include <QCoreApplication>
+#include <QEasingCurve>
+#include <QTime>
+
+QT_BEGIN_NAMESPACE
+
+struct Update {
+ Update(QmlTimeLineValue *_g, qreal _v)
+ : g(_g), v(_v) {}
+ Update(const QmlTimeLineEvent &_e)
+ : g(0), v(0), e(_e) {}
+
+ QmlTimeLineValue *g;
+ qreal v;
+ QmlTimeLineEvent e;
+};
+
+struct QmlTimeLinePrivate
+{
+ QmlTimeLinePrivate(QmlTimeLine *);
+
+ struct Op {
+ enum Type {
+ Pause,
+ Set,
+ Move,
+ MoveBy,
+ Accel,
+ AccelDistance,
+ Execute
+ };
+ Op() {}
+ Op(Type t, int l, qreal v, qreal v2, int o,
+ const QmlTimeLineEvent &ev = QmlTimeLineEvent(), const QEasingCurve &es = QEasingCurve())
+ : type(t), length(l), value(v), value2(v2), order(o), event(ev),
+ easing(es) {}
+ Op(const Op &o)
+ : type(o.type), length(o.length), value(o.value), value2(o.value2),
+ order(o.order), event(o.event), easing(o.easing) {}
+ Op &operator=(const Op &o) {
+ type = o.type; length = o.length; value = o.value;
+ value2 = o.value2; order = o.order; event = o.event;
+ easing = o.easing;
+ return *this;
+ }
+
+ Type type;
+ int length;
+ qreal value;
+ qreal value2;
+
+ int order;
+ QmlTimeLineEvent event;
+ QEasingCurve easing;
+ };
+ struct TimeLine
+ {
+ TimeLine() : length(0), consumedOpLength(0), base(0.) {}
+ QList<Op> ops;
+ int length;
+ int consumedOpLength;
+ qreal base;
+ };
+
+ int length;
+ int syncPoint;
+ typedef QHash<QmlTimeLineObject *, TimeLine> Ops;
+ Ops ops;
+ QmlTimeLine *q;
+
+ void add(QmlTimeLineObject &, const Op &);
+ qreal value(const Op &op, int time, qreal base, bool *) const;
+
+ int advance(int);
+
+ bool clockRunning;
+ int prevTime;
+
+ int order;
+
+ QmlTimeLine::SyncMode syncMode;
+ int syncAdj;
+ QList<QPair<int, Update> > *updateQueue;
+};
+
+QmlTimeLinePrivate::QmlTimeLinePrivate(QmlTimeLine *parent)
+: length(0), syncPoint(0), q(parent), clockRunning(false), prevTime(0), order(0), syncMode(QmlTimeLine::LocalSync), syncAdj(0), updateQueue(0)
+{
+}
+
+void QmlTimeLinePrivate::add(QmlTimeLineObject &g, const Op &o)
+{
+ if (g._t && g._t != q) {
+ qWarning() << "QmlTimeLine: Cannot modify a QmlTimeLineValue owned by"
+ << "another timeline.";
+ return;
+ }
+ g._t = q;
+
+ Ops::Iterator iter = ops.find(&g);
+ if (iter == ops.end()) {
+ iter = ops.insert(&g, TimeLine());
+ if (syncPoint > 0)
+ q->pause(g, syncPoint);
+ }
+ if (!iter->ops.isEmpty() &&
+ o.type == Op::Pause &&
+ iter->ops.last().type == Op::Pause) {
+ iter->ops.last().length += o.length;
+ iter->length += o.length;
+ } else {
+ iter->ops.append(o);
+ iter->length += o.length;
+ }
+
+ if (iter->length > length)
+ length = iter->length;
+
+ if (!clockRunning) {
+ q->stop();
+ prevTime = 0;
+ clockRunning = true;
+
+ if (syncMode == QmlTimeLine::LocalSync) {
+ syncAdj = -1;
+ } else {
+ syncAdj = 0;
+ }
+ q->start();
+/* q->tick(0);
+ if (syncMode == QmlTimeLine::LocalSync) {
+ syncAdj = -1;
+ } else {
+ syncAdj = 0;
+ }
+ */
+ }
+}
+
+qreal QmlTimeLinePrivate::value(const Op &op, int time, qreal base, bool *changed) const
+{
+ Q_ASSERT(time >= 0);
+ Q_ASSERT(time <= op.length);
+ *changed = true;
+
+ switch(op.type) {
+ case Op::Pause:
+ *changed = false;
+ return base;
+ case Op::Set:
+ return op.value;
+ case Op::Move:
+ if (time == 0) {
+ return base;
+ } else if (time == (op.length)) {
+ return op.value;
+ } else {
+ qreal delta = op.value - base;
+ qreal pTime = (qreal)(time) / (qreal)op.length;
+ if (op.easing.type() == QEasingCurve::Linear)
+ return base + delta * pTime;
+ else
+ return base + delta * op.easing.valueForProgress(pTime);
+ }
+ case Op::MoveBy:
+ if (time == 0) {
+ return base;
+ } else if (time == (op.length)) {
+ return base + op.value;
+ } else {
+ qreal delta = op.value;
+ qreal pTime = (qreal)(time) / (qreal)op.length;
+ if (op.easing.type() == QEasingCurve::Linear)
+ return base + delta * pTime;
+ else
+ return base + delta * op.easing.valueForProgress(pTime);
+ }
+ case Op::Accel:
+ if (time == 0) {
+ return base;
+ } else {
+ qreal t = (qreal)(time) / 1000.0f;
+ qreal delta = op.value * t + 0.5f * op.value2 * t * t;
+ return base + delta;
+ }
+ case Op::AccelDistance:
+ if (time == 0) {
+ return base;
+ } else if (time == (op.length)) {
+ return base + op.value2;
+ } else {
+ qreal t = (qreal)(time) / 1000.0f;
+ qreal accel = -1.0f * 1000.0f * op.value / (qreal)op.length;
+ qreal delta = op.value * t + 0.5f * accel * t * t;
+ return base + delta;
+
+ }
+ case Op::Execute:
+ op.event.execute();
+ *changed = false;
+ return -1;
+ }
+
+ return base;
+}
+
+/*!
+ \internal
+ \class QmlTimeLine
+ \ingroup group_animation
+ \brief The QmlTimeLine class provides a timeline for controlling animations.
+
+ QmlTimeLine is similar to QTimeLine except:
+ \list
+ \i It updates QmlTimeLineValue instances directly, rather than maintaining a single
+ current value.
+
+ For example, the following animates a simple value over 200 milliseconds:
+ \code
+ QmlTimeLineValue v(<starting value>);
+ QmlTimeLine tl;
+ tl.move(v, 100., 200);
+ tl.start()
+ \endcode
+
+ If your program needs to know when values are changed, it can either
+ connect to the QmlTimeLine's updated() signal, or inherit from QmlTimeLineValue
+ and reimplement the QmlTimeLineValue::setValue() method.
+
+ \i Supports multiple QmlTimeLineValue, arbitrary start and end values and allows
+ animations to be strung together for more complex effects.
+
+ For example, the following animation moves the x and y coordinates of
+ an object from wherever they are to the position (100, 100) in 50
+ milliseconds and then further animates them to (100, 200) in 50
+ milliseconds:
+
+ \code
+ QmlTimeLineValue x(<starting value>);
+ QmlTimeLineValue y(<starting value>);
+
+ QmlTimeLine tl;
+ tl.start();
+
+ tl.move(x, 100., 50);
+ tl.move(y, 100., 50);
+ tl.move(y, 200., 50);
+ \endcode
+
+ \i All QmlTimeLine instances share a single, synchronized clock.
+
+ Actions scheduled within the same event loop tick are scheduled
+ synchronously against each other, regardless of the wall time between the
+ scheduling. Synchronized scheduling applies both to within the same
+ QmlTimeLine and across separate QmlTimeLine's within the same process.
+
+ \endlist
+
+ Currently easing functions are not supported.
+*/
+
+
+/*!
+ Construct a new QmlTimeLine with the specified \a parent.
+*/
+QmlTimeLine::QmlTimeLine(QObject *parent)
+: QAbstractAnimation(parent)
+{
+ d = new QmlTimeLinePrivate(this);
+}
+
+/*!
+ Destroys the time line. Any inprogress animations are canceled, but not
+ completed.
+*/
+QmlTimeLine::~QmlTimeLine()
+{
+ for (QmlTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter)
+ iter.key()->_t = 0;
+
+ delete d; d = 0;
+}
+
+/*!
+ \enum QmlTimeLine::SyncMode
+ */
+
+/*!
+ Return the timeline's synchronization mode.
+ */
+QmlTimeLine::SyncMode QmlTimeLine::syncMode() const
+{
+ return d->syncMode;
+}
+
+/*!
+ Set the timeline's synchronization mode to \a syncMode.
+ */
+void QmlTimeLine::setSyncMode(SyncMode syncMode)
+{
+ d->syncMode = syncMode;
+}
+
+/*!
+ Pause \a obj for \a time milliseconds.
+*/
+void QmlTimeLine::pause(QmlTimeLineObject &obj, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Pause, time, 0., 0., d->order++);
+ d->add(obj, op);
+}
+
+/*!
+ Execute the \a event.
+ */
+void QmlTimeLine::execute(const QmlTimeLineEvent &event)
+{
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Execute, 0, 0, 0., d->order++, event);
+ d->add(*event.eventObject(), op);
+}
+
+/*!
+ Set the \a value of \a timeLineValue.
+*/
+void QmlTimeLine::set(QmlTimeLineValue &timeLineValue, qreal value)
+{
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Set, 0, value, 0., d->order++);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Decelerate \a timeLineValue from the starting \a velocity to zero at the
+ given \a acceleration rate. Although the \a acceleration is technically
+ a deceleration, it should always be positive. The QmlTimeLine will ensure
+ that the deceleration is in the opposite direction to the initial velocity.
+*/
+int QmlTimeLine::accel(QmlTimeLineValue &timeLineValue, qreal velocity, qreal acceleration)
+{
+ if ((velocity > 0.0f) == (acceleration > 0.0f))
+ acceleration = acceleration * -1.0f;
+
+ int time = static_cast<int>(-1000 * velocity / acceleration);
+
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
+ d->add(timeLineValue, op);
+
+ return time;
+}
+
+/*!
+ \overload
+
+ Decelerate \a timeLineValue from the starting \a velocity to zero at the
+ given \a acceleration rate over a maximum distance of maxDistance.
+
+ If necessary, QmlTimeLine will reduce the acceleration to ensure that the
+ entire operation does not require a move of more than \a maxDistance.
+ \a maxDistance should always be positive.
+*/
+int QmlTimeLine::accel(QmlTimeLineValue &timeLineValue, qreal velocity, qreal acceleration, qreal maxDistance)
+{
+ Q_ASSERT(acceleration >= 0.0f && maxDistance >= 0.0f);
+
+ qreal maxAccel = (velocity * velocity) / (2.0f * maxDistance);
+ if (maxAccel > acceleration)
+ acceleration = maxAccel;
+
+ if ((velocity > 0.0f) == (acceleration > 0.0f))
+ acceleration = acceleration * -1.0f;
+
+ int time = static_cast<int>(-1000 * velocity / acceleration);
+
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
+ d->add(timeLineValue, op);
+
+ return time;
+}
+
+/*!
+ Decelerate \a timeLineValue from the starting \a velocity to zero over the given
+ \a distance. This is like accel(), but the QmlTimeLine calculates the exact
+ deceleration to use.
+
+ \a distance should be positive.
+*/
+int QmlTimeLine::accelDistance(QmlTimeLineValue &timeLineValue, qreal velocity, qreal distance)
+{
+ if (distance == 0.0f || velocity == 0.0f)
+ return -1;
+ Q_ASSERT((distance >= 0.0f) == (velocity >= 0.0f));
+
+ int time = static_cast<int>(1000 * (2.0f * distance) / velocity);
+
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::AccelDistance, time, velocity, distance, d->order++);
+ d->add(timeLineValue, op);
+
+ return time;
+}
+
+/*!
+ Linearly change the \a timeLineValue from its current value to the given
+ \a destination value over \a time milliseconds.
+*/
+void QmlTimeLine::move(QmlTimeLineValue &timeLineValue, qreal destination, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Change the \a timeLineValue from its current value to the given \a destination
+ value over \a time milliseconds using the \a easing curve.
+ */
+void QmlTimeLine::move(QmlTimeLineValue &timeLineValue, qreal destination, const QEasingCurve &easing, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++, QmlTimeLineEvent(), easing);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Linearly change the \a timeLineValue from its current value by the \a change amount
+ over \a time milliseconds.
+*/
+void QmlTimeLine::moveBy(QmlTimeLineValue &timeLineValue, qreal change, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Change the \a timeLineValue from its current value by the \a change amount over
+ \a time milliseconds using the \a easing curve.
+ */
+void QmlTimeLine::moveBy(QmlTimeLineValue &timeLineValue, qreal change, const QEasingCurve &easing, int time)
+{
+ if (time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++, QmlTimeLineEvent(), easing);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Cancel (but don't complete) all scheduled actions for \a timeLineValue.
+*/
+void QmlTimeLine::reset(QmlTimeLineValue &timeLineValue)
+{
+ if (!timeLineValue._t)
+ return;
+ if (timeLineValue._t != this) {
+ qWarning() << "QmlTimeLine: Cannot reset a QmlTimeLineValue owned by another timeline.";
+ return;
+ }
+ remove(&timeLineValue);
+ timeLineValue._t = 0;
+}
+
+int QmlTimeLine::duration() const
+{
+ return -1;
+}
+
+/*!
+ Synchronize the end point of \a timeLineValue to the endpoint of \a syncTo
+ within this timeline.
+
+ Following operations on \a timeLineValue in this timeline will be scheduled after
+ all the currently scheduled actions on \a syncTo are complete. In
+ psuedo-code this is equivalent to:
+ \code
+ QmlTimeLine::pause(timeLineValue, min(0, length_of(syncTo) - length_of(timeLineValue)))
+ \endcode
+*/
+void QmlTimeLine::sync(QmlTimeLineValue &timeLineValue, QmlTimeLineValue &syncTo)
+{
+ QmlTimeLinePrivate::Ops::Iterator iter = d->ops.find(&syncTo);
+ if (iter == d->ops.end())
+ return;
+ int length = iter->length;
+
+ iter = d->ops.find(&timeLineValue);
+ if (iter == d->ops.end()) {
+ pause(timeLineValue, length);
+ } else {
+ int glength = iter->length;
+ pause(timeLineValue, length - glength);
+ }
+}
+
+/*!
+ Synchronize the end point of \a timeLineValue to the endpoint of the longest
+ action cursrently scheduled in the timeline.
+
+ In psuedo-code, this is equivalent to:
+ \code
+ QmlTimeLine::pause(timeLineValue, length_of(timeline) - length_of(timeLineValue))
+ \endcode
+*/
+void QmlTimeLine::sync(QmlTimeLineValue &timeLineValue)
+{
+ QmlTimeLinePrivate::Ops::Iterator iter = d->ops.find(&timeLineValue);
+ if (iter == d->ops.end()) {
+ pause(timeLineValue, d->length);
+ } else {
+ pause(timeLineValue, d->length - iter->length);
+ }
+}
+
+/*
+ Synchronize all currently and future scheduled values in this timeline to
+ the longest action currently scheduled.
+
+ For example:
+ \code
+ value1->setValue(0.);
+ value2->setValue(0.);
+ value3->setValue(0.);
+ QmlTimeLine tl;
+ ...
+ tl.move(value1, 10, 200);
+ tl.move(value2, 10, 100);
+ tl.sync();
+ tl.move(value2, 20, 100);
+ tl.move(value3, 20, 100);
+ \endcode
+
+ will result in:
+
+ \table
+ \header \o \o 0ms \o 50ms \o 100ms \o 150ms \o 200ms \o 250ms \o 300ms
+ \row \o value1 \o 0 \o 2.5 \o 5.0 \o 7.5 \o 10 \o 10 \o 10
+ \row \o value2 \o 0 \o 5.0 \o 10.0 \o 10.0 \o 10.0 \o 15.0 \o 20.0
+ \row \o value2 \o 0 \o 0 \o 0 \o 0 \o 0 \o 10.0 \o 20.0
+ \endtable
+*/
+
+/*void QmlTimeLine::sync()
+{
+ for (QmlTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter)
+ pause(*iter.key(), d->length - iter->length);
+ d->syncPoint = d->length;
+}*/
+
+/*!
+ \internal
+
+ Temporary hack.
+ */
+void QmlTimeLine::setSyncPoint(int sp)
+{
+ d->syncPoint = sp;
+}
+
+/*!
+ \internal
+
+ Temporary hack.
+ */
+int QmlTimeLine::syncPoint() const
+{
+ return d->syncPoint;
+}
+
+/*!
+ Returns true if the timeline is active. An active timeline is one where
+ QmlTimeLineValue actions are still pending.
+*/
+bool QmlTimeLine::isActive() const
+{
+ return !d->ops.isEmpty();
+}
+
+/*!
+ Completes the timeline. All queued actions are played to completion, and then discarded. For example,
+ \code
+ QmlTimeLineValue v(0.);
+ QmlTimeLine tl;
+ tl.move(v, 100., 1000.);
+ // 500 ms passes
+ // v.value() == 50.
+ tl.complete();
+ // v.value() == 100.
+ \endcode
+*/
+void QmlTimeLine::complete()
+{
+ d->advance(d->length);
+}
+
+/*!
+ Resets the timeline. All queued actions are discarded and QmlTimeLineValue's retain their current value. For example,
+ \code
+ QmlTimeLineValue v(0.);
+ QmlTimeLine tl;
+ tl.move(v, 100., 1000.);
+ // 500 ms passes
+ // v.value() == 50.
+ tl.clear();
+ // v.value() == 50.
+ \endcode
+*/
+void QmlTimeLine::clear()
+{
+ for (QmlTimeLinePrivate::Ops::ConstIterator iter = d->ops.begin(); iter != d->ops.end(); ++iter)
+ iter.key()->_t = 0;
+ d->ops.clear();
+ d->length = 0;
+ d->syncPoint = 0;
+ //XXX need stop here?
+}
+
+int QmlTimeLine::time() const
+{
+ return d->prevTime;
+}
+
+/*!
+ \fn void QmlTimeLine::updated()
+
+ Emitted each time the timeline modifies QmlTimeLineValues. Even if multiple
+ QmlTimeLineValues are changed, this signal is only emitted once for each clock tick.
+*/
+
+void QmlTimeLine::updateCurrentTime(int v)
+{
+ if (d->syncAdj == -1)
+ d->syncAdj = v;
+ v -= d->syncAdj;
+
+ int timeChanged = v - d->prevTime;
+#if 0
+ if (!timeChanged)
+ return;
+#endif
+ d->prevTime = v;
+ d->advance(timeChanged);
+ emit updated();
+
+ // Do we need to stop the clock?
+ if (d->ops.isEmpty()) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = false;
+ emit completed();
+ } /*else if (pauseTime > 0) {
+ GfxClock::cancelClock();
+ d->prevTime = 0;
+ GfxClock::pauseFor(pauseTime);
+ d->syncAdj = 0;
+ d->clockRunning = false;
+ }*/ else if (/*!GfxClock::isActive()*/ state() != Running) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = true;
+ d->syncAdj = 0;
+ start();
+ }
+}
+
+bool operator<(const QPair<int, Update> &lhs,
+ const QPair<int, Update> &rhs)
+{
+ return lhs.first < rhs.first;
+}
+
+int QmlTimeLinePrivate::advance(int t)
+{
+ int pauseTime = -1;
+
+ // XXX - surely there is a more efficient way?
+ do {
+ pauseTime = -1;
+ // Minimal advance time
+ int advanceTime = t;
+ for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ++iter) {
+ TimeLine &tl = *iter;
+ Op &op = tl.ops.first();
+ int length = op.length - tl.consumedOpLength;
+
+ if (length < advanceTime) {
+ advanceTime = length;
+ if (advanceTime == 0)
+ break;
+ }
+ }
+ t -= advanceTime;
+
+ // Process until then. A zero length advance time will only process
+ // sets.
+ QList<QPair<int, Update> > updates;
+
+ for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ) {
+ QmlTimeLineValue *v = static_cast<QmlTimeLineValue *>(iter.key());
+ TimeLine &tl = *iter;
+ Q_ASSERT(!tl.ops.isEmpty());
+
+ do {
+ Op &op = tl.ops.first();
+ if (advanceTime == 0 && op.length != 0)
+ continue;
+
+ if (tl.consumedOpLength == 0 &&
+ op.type != Op::Pause &&
+ op.type != Op::Execute)
+ tl.base = v->value();
+
+ if ((tl.consumedOpLength + advanceTime) == op.length) {
+ if (op.type == Op::Execute) {
+ updates << qMakePair(op.order, Update(op.event));
+ } else {
+ bool changed = false;
+ qreal val = value(op, op.length, tl.base, &changed);
+ if (changed)
+ updates << qMakePair(op.order, Update(v, val));
+ }
+ tl.length -= qMin(advanceTime, tl.length);
+ tl.consumedOpLength = 0;
+ tl.ops.removeFirst();
+ } else {
+ tl.consumedOpLength += advanceTime;
+ bool changed = false;
+ qreal val = value(op, tl.consumedOpLength, tl.base, &changed);
+ if (changed)
+ updates << qMakePair(op.order, Update(v, val));
+ tl.length -= qMin(advanceTime, tl.length);
+ break;
+ }
+
+ } while(!tl.ops.isEmpty() && advanceTime == 0 && tl.ops.first().length == 0);
+
+
+ if (tl.ops.isEmpty()) {
+ iter = ops.erase(iter);
+ v->_t = 0;
+ } else {
+ if (tl.ops.first().type == Op::Pause && pauseTime != 0) {
+ int opPauseTime = tl.ops.first().length - tl.consumedOpLength;
+ if (pauseTime == -1 || opPauseTime < pauseTime)
+ pauseTime = opPauseTime;
+ } else {
+ pauseTime = 0;
+ }
+ ++iter;
+ }
+ }
+
+ length -= qMin(length, advanceTime);
+ syncPoint -= advanceTime;
+
+ qSort(updates.begin(), updates.end());
+ updateQueue = &updates;
+ for (int ii = 0; ii < updates.count(); ++ii) {
+ const Update &v = updates.at(ii).second;
+ if (v.g)
+ v.g->setValue(v.v);
+ else
+ v.e.execute();
+ }
+ updateQueue = 0;
+ } while(t);
+
+ return pauseTime;
+}
+
+void QmlTimeLine::remove(QmlTimeLineObject *v)
+{
+ QmlTimeLinePrivate::Ops::Iterator iter = d->ops.find(v);
+ Q_ASSERT(iter != d->ops.end());
+
+ int len = iter->length;
+ d->ops.erase(iter);
+ if (len == d->length) {
+ // We need to recalculate the length
+ d->length = 0;
+ for (QmlTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter) {
+
+ if (iter->length > d->length)
+ d->length = iter->length;
+
+ }
+ }
+ if (d->ops.isEmpty()) {
+ stop();
+ d->clockRunning = false;
+ } else if (/*!GfxClock::isActive()*/ state() != Running) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = true;
+
+ if (d->syncMode == QmlTimeLine::LocalSync) {
+ d->syncAdj = -1;
+ } else {
+ d->syncAdj = 0;
+ }
+ start();
+ }
+
+ if (d->updateQueue) {
+ for (int ii = 0; ii < d->updateQueue->count(); ++ii) {
+ if (d->updateQueue->at(ii).second.g == v ||
+ d->updateQueue->at(ii).second.e.eventObject() == v) {
+ d->updateQueue->removeAt(ii);
+ --ii;
+ }
+ }
+ }
+
+
+}
+
+/*!
+ \internal
+ \class QmlTimeLineValue
+ \ingroup group_animation
+ \brief The QmlTimeLineValue class provides a value that can be modified by QmlTimeLine.
+*/
+
+/*!
+ \fn QmlTimeLineValue::QmlTimeLineValue(qreal value = 0)
+
+ Construct a new QmlTimeLineValue with an initial \a value.
+*/
+
+/*!
+ \fn qreal QmlTimeLineValue::value() const
+
+ Return the current value.
+*/
+
+/*!
+ \fn void QmlTimeLineValue::setValue(qreal value)
+
+ Set the current \a value.
+*/
+
+/*!
+ \fn QmlTimeLine *QmlTimeLineValue::timeLine() const
+
+ If a QmlTimeLine is operating on this value, return a pointer to it,
+ otherwise return null.
+*/
+
+
+QmlTimeLineObject::QmlTimeLineObject()
+: _t(0)
+{
+}
+
+QmlTimeLineObject::~QmlTimeLineObject()
+{
+ if (_t) {
+ _t->remove(this);
+ _t = 0;
+ }
+}
+
+QmlTimeLineEvent::QmlTimeLineEvent()
+: d0(0), d1(0), d2(0)
+{
+}
+
+QmlTimeLineEvent::QmlTimeLineEvent(const QmlTimeLineEvent &o)
+: d0(o.d0), d1(o.d1), d2(o.d2)
+{
+}
+
+QmlTimeLineEvent &QmlTimeLineEvent::operator=(const QmlTimeLineEvent &o)
+{
+ d0 = o.d0;
+ d1 = o.d1;
+ d2 = o.d2;
+ return *this;
+}
+
+void QmlTimeLineEvent::execute() const
+{
+ d0(d1);
+}
+
+QmlTimeLineObject *QmlTimeLineEvent::eventObject() const
+{
+ return d2;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/timeline/qmltimeline.h b/src/declarative/timeline/qmltimeline.h
new file mode 100644
index 0000000..ce9d1f2
--- /dev/null
+++ b/src/declarative/timeline/qmltimeline.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTIMELINE_H
+#define QMLTIMELINE_H
+
+#include <QObject>
+#include <qfxglobal.h>
+#include <QAbstractAnimation>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QEasingCurve;
+class QmlTimeLineValue;
+class QmlTimeLineEvent;
+struct QmlTimeLinePrivate;
+class QmlTimeLineObject;
+class Q_DECLARATIVE_EXPORT QmlTimeLine : public QAbstractAnimation
+{
+Q_OBJECT
+public:
+ QmlTimeLine(QObject *parent = 0);
+ ~QmlTimeLine();
+
+ enum SyncMode { LocalSync, GlobalSync };
+ SyncMode syncMode() const;
+ void setSyncMode(SyncMode);
+
+ void pause(QmlTimeLineObject &, int);
+ void execute(const QmlTimeLineEvent &);
+ void set(QmlTimeLineValue &, qreal);
+
+ int accel(QmlTimeLineValue &, qreal velocity, qreal accel);
+ int accel(QmlTimeLineValue &, qreal velocity, qreal accel, qreal maxDistance);
+ int accelDistance(QmlTimeLineValue &, qreal velocity, qreal distance);
+
+ void move(QmlTimeLineValue &, qreal destination, int time = 500);
+ void move(QmlTimeLineValue &, qreal destination, const QEasingCurve &, int time = 500);
+ void moveBy(QmlTimeLineValue &, qreal change, int time = 500);
+ void moveBy(QmlTimeLineValue &, qreal change, const QEasingCurve &, int time = 500);
+
+ void sync();
+ void setSyncPoint(int);
+ int syncPoint() const;
+
+ void sync(QmlTimeLineValue &);
+ void sync(QmlTimeLineValue &, QmlTimeLineValue &);
+
+ void reset(QmlTimeLineValue &);
+
+ void complete();
+ void clear();
+ bool isActive() const;
+
+ int time() const;
+
+ virtual int duration() const;
+Q_SIGNALS:
+ void updated();
+ void completed();
+
+protected:
+ virtual void updateCurrentTime(int);
+
+private:
+ void remove(QmlTimeLineObject *);
+ friend class QmlTimeLineObject;
+ friend struct QmlTimeLinePrivate;
+ QmlTimeLinePrivate *d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlTimeLineObject
+{
+public:
+ QmlTimeLineObject();
+ virtual ~QmlTimeLineObject();
+
+protected:
+ friend class QmlTimeLine;
+ friend struct QmlTimeLinePrivate;
+ QmlTimeLine *_t;
+};
+
+class Q_DECLARATIVE_EXPORT QmlTimeLineValue : public QmlTimeLineObject
+{
+public:
+ QmlTimeLineValue(qreal v = 0.) : _v(v) {}
+
+ qreal value() const { return _v; }
+ virtual void setValue(qreal v) { _v = v; }
+
+ QmlTimeLine *timeLine() const { return _t; }
+
+ operator qreal() const { return _v; }
+ QmlTimeLineValue &operator=(qreal v) { setValue(v); return *this; }
+private:
+ friend class QmlTimeLine;
+ friend struct QmlTimeLinePrivate;
+ qreal _v;
+};
+
+class Q_DECLARATIVE_EXPORT QmlTimeLineEvent
+{
+public:
+ QmlTimeLineEvent();
+ QmlTimeLineEvent(const QmlTimeLineEvent &o);
+
+ template<class T, void (T::*method)()>
+ QmlTimeLineEvent(QmlTimeLineObject *b, T *c)
+ {
+ d0 = &callFunc<T, method>;
+ d1 = (void *)c;
+ d2 = b;
+ }
+
+ template<class T, void (T::*method)()>
+ static QmlTimeLineEvent timeLineEvent(QmlTimeLineObject *b, T *c)
+ {
+ QmlTimeLineEvent rv;
+ rv.d0 = &callFunc<T, method>;
+ rv.d1 = (void *)c;
+ rv.d2 = b;
+ return rv;
+ }
+
+ QmlTimeLineEvent &operator=(const QmlTimeLineEvent &o);
+ void execute() const;
+ QmlTimeLineObject *eventObject() const;
+
+private:
+ typedef void (*CallFunc)(void *c);
+
+ template <class T, void (T::*method)()>
+ static void callFunc(void *c)
+ {
+ T *cls = (T *)c;
+ (cls->*method)();
+ }
+ CallFunc d0;
+ void *d1;
+ QmlTimeLineObject *d2;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/timeline/qmltimelinevalueproxy.h b/src/declarative/timeline/qmltimelinevalueproxy.h
new file mode 100644
index 0000000..853db4e
--- /dev/null
+++ b/src/declarative/timeline/qmltimelinevalueproxy.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTIMELINEVALUEPROXY_H
+#define QMLTIMELINEVALUEPROXY_H
+
+#include "qmltimeline.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+template<class T>
+class QmlTimeLineValueProxy : public QmlTimeLineValue
+{
+public:
+ QmlTimeLineValueProxy(T *cls, void (T::*func)(qreal), qreal v = 0.)
+ : QmlTimeLineValue(v), _class(cls), _setFunctionReal(func), _setFunctionInt(0)
+ {
+ Q_ASSERT(_class);
+ }
+
+ QmlTimeLineValueProxy(T *cls, void (T::*func)(int), qreal v = 0.)
+ : QmlTimeLineValue(v), _class(cls), _setFunctionReal(0), _setFunctionInt(func)
+ {
+ Q_ASSERT(_class);
+ }
+
+ virtual void setValue(qreal v)
+ {
+ QmlTimeLineValue::setValue(v);
+ if (_setFunctionReal) (_class->*_setFunctionReal)(v);
+ else if (_setFunctionInt) (_class->*_setFunctionInt)((int)v);
+ }
+
+private:
+ T *_class;
+ void (T::*_setFunctionReal)(qreal);
+ void (T::*_setFunctionInt)(int);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif//QMLTIMELINEVALUEPROXY_H
diff --git a/src/declarative/timeline/timeline.pri b/src/declarative/timeline/timeline.pri
new file mode 100644
index 0000000..a7b3cb9
--- /dev/null
+++ b/src/declarative/timeline/timeline.pri
@@ -0,0 +1,7 @@
+SOURCES += \
+ timeline/qmltimeline.cpp \
+
+HEADERS += \
+ timeline/qmltimeline.h \
+ timeline/qmltimelinevalueproxy.h \
+
diff --git a/src/declarative/util/qbindablemap.cpp b/src/declarative/util/qbindablemap.cpp
new file mode 100644
index 0000000..c8c8ced
--- /dev/null
+++ b/src/declarative/util/qbindablemap.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbindablemap.h"
+#include <qmlopenmetaobject.h>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+//QBindableMapMetaObject lets us listen for changes coming from QML
+//so we can emit the changed signal.
+class QBindableMapMetaObject : public QmlOpenMetaObject
+{
+public:
+ QBindableMapMetaObject(QBindableMap *obj) : QmlOpenMetaObject(obj)
+ {
+ map = obj;
+ }
+
+protected:
+ virtual void propertyWrite(int index)
+ {
+ map->emitChanged(QLatin1String(name(index)));
+ }
+
+private:
+ QBindableMap *map;
+};
+
+/*!
+ \class QBindableMap
+ \brief The QBindableMap class allows you to set key-value pairs that can be used in bindings.
+
+ QBindableMap provides a convenient way to expose domain data to the UI layer.
+ The following example shows how you might declare data in C++ and then
+ access it in QML.
+
+ Setup in C++:
+ \code
+ //create our data
+ QBindableMap ownerData;
+ ownerData.setValue("name", QVariant(QString("John Smith")));
+ ownerData.setValue("phone", QVariant(QString("555-5555")));
+
+ //expose it to the UI layer
+ QmlContext *ctxt = view->bindContext();
+ ctxt->setProperty("owner", &data);
+ \endcode
+
+ Then, in QML:
+ \code
+ Text { text: owner.name }
+ Text { text: owner.phone }
+ \endcode
+
+ The binding is dynamic - whenever a key's value is updated, anything bound to that
+ key will be updated as well.
+
+ To detect value changes made in the UI layer you can connect to the changed() signal.
+ However, note that changed() is \b NOT emitted when changes are made by calling setValue()
+ or clearValue() - it is only emitted when a value is updated from QML.
+*/
+
+// is there a more efficient way to store/return keys?
+// (or should we just provide an iterator or something else instead?)
+// can we provide a way to clear keys?
+// do we want to make any claims regarding key ordering?
+// should we have signals for insertion and and deletion -- becoming more model like
+// should we emit change for our own changes as well?
+// Bug or Feature?: values can be created in QML (owner.somethingElse = "Hello") will create somethingElse property. (need to verify if this is actually the case)
+// Bug or Feature?: all values are read-write (there are no read-only values)
+
+/*!
+ Constructs a bindable map with parent object \a parent.
+*/
+QBindableMap::QBindableMap(QObject *parent)
+: QObject(parent)
+{
+ m_mo = new QBindableMapMetaObject(this);
+}
+
+/*!
+ Destroys the bindable map.
+*/
+QBindableMap::~QBindableMap()
+{
+}
+
+/*!
+ Clears the value (if any) associated with \a key.
+*/
+void QBindableMap::clearValue(const QString &key)
+{
+ //m_keys.remove(); //###
+ m_mo->setValue(key.toLatin1(), QVariant());
+ //emit changed(key);
+}
+
+/*!
+ Returns the value associated with \a key.
+
+ If no value has been set for this key (or if the value has been cleared),
+ an invalid QVariant is returned.
+*/
+QVariant QBindableMap::value(const QString &key) const
+{
+ return m_mo->value(key.toLatin1());
+}
+
+/*!
+ Sets the value associated with \a key to \a value.
+
+ If the key doesn't exist, it is automatically created.
+*/
+void QBindableMap::setValue(const QString &key, QVariant value)
+{
+ if (!m_keys.contains(key))
+ m_keys.append(key);
+ m_mo->setValue(key.toLatin1(), value);
+ //emit changed(key);
+}
+
+/*!
+ Returns the list of keys.
+
+ Keys that have been cleared will still appear in this list, even though their
+ associated values are invalid QVariants.
+*/
+QStringList QBindableMap::keys() const
+{
+ return m_keys;
+}
+
+/*!
+ \fn void QBindableMap::changed(const QString &key)
+ This signal is emitted whenever one of the values in the map is changed. \a key
+ is the key corresponding to the value that was changed.
+ */
+
+void QBindableMap::emitChanged(const QString &key)
+{
+ emit changed(key);
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qbindablemap.h b/src/declarative/util/qbindablemap.h
new file mode 100644
index 0000000..d617867
--- /dev/null
+++ b/src/declarative/util/qbindablemap.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBINDABLEMAP_H
+#define QBINDABLEMAP_H
+
+#include <qfxglobal.h>
+#include <QObject>
+#include <QHash>
+#include <QStringList>
+#include <QVariant>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QBindableMapMetaObject;
+class Q_DECLARATIVE_EXPORT QBindableMap : public QObject
+{
+ Q_OBJECT
+public:
+ QBindableMap(QObject *parent = 0);
+ virtual ~QBindableMap();
+
+ QVariant value(const QString &key) const;
+ void setValue(const QString &key, QVariant value);
+ void clearValue(const QString &key);
+
+ Q_INVOKABLE QStringList keys() const;
+
+Q_SIGNALS:
+ void changed(const QString &key);
+
+private:
+ Q_DISABLE_COPY(QBindableMap)
+ void emitChanged(const QString &key);
+ QBindableMapMetaObject *m_mo;
+ QStringList m_keys;
+ friend class QBindableMapMetaObject;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/util/qfxglobal.h b/src/declarative/util/qfxglobal.h
new file mode 100644
index 0000000..887351d
--- /dev/null
+++ b/src/declarative/util/qfxglobal.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXGLOBAL_H
+#define QFXGLOBAL_H
+
+#include <qglobal.h>
+#include <QObject>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+#if defined(QT_OPENGL_ES_1)
+#define QFX_CONFIGURATION_OPENGL1
+#elif defined(QT_OPENGL_ES_2)
+#define QFX_CONFIGURATION_OPENGL2
+#else
+#define QFX_CONFIGURATION_SOFTWARE
+#endif
+
+/*
+ The choices of renderer are:
+ QFX_RENDER_QPAINTER
+ QFX_RENDER_OPENGL1
+ QFX_RENDER_OPENGL2
+ To simplify code, if either of the OpenGL renderers are used,
+ QFX_RENDER_OPENGL is also defined.
+*/
+
+#if defined(QFX_CONFIGURATION_OPENGL2)
+
+#define QFX_RENDER_OPENGL
+#define QFX_RENDER_OPENGL2
+
+#elif defined(QFX_CONFIGURATION_OPENGL1)
+
+#define QFX_RENDER_OPENGL
+#define QFX_RENDER_OPENGL1
+
+#elif defined(QFX_CONFIGURATION_SOFTWARE)
+
+#define QFX_RENDER_QPAINTER
+
+#endif
+
+#define DEFINE_BOOL_CONFIG_OPTION(name, var) \
+ static bool name() \
+ { \
+ static enum { Yes, No, Unknown } status = Unknown; \
+ if (status == Unknown) { \
+ QByteArray v = qgetenv(#var); \
+ bool value = !v.isEmpty() && v != "0" && v != "false"; \
+ if (value) status = Yes; \
+ else status = No; \
+ } \
+ return status == Yes; \
+ }
+
+struct QFx_DerivedObject : public QObject
+{
+ void setParent_noEvent(QObject *parent) {
+ bool sce = d_ptr->sendChildEvents;
+ d_ptr->sendChildEvents = false;
+ setParent(parent);
+ d_ptr->sendChildEvents = sce;
+ }
+};
+
+/*!
+ Makes the \a object a child of \a parent. Note that when using this method,
+ neither \a parent nor the object's previous parent (if it had one) will
+ receive ChildRemoved or ChildAdded events.
+*/
+inline void QFx_setParent_noEvent(QObject *object, QObject *parent)
+{
+ static_cast<QFx_DerivedObject *>(object)->setParent_noEvent(parent);
+}
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QFXGLOBAL_H
diff --git a/src/declarative/util/qfxperf.cpp b/src/declarative/util/qfxperf.cpp
new file mode 100644
index 0000000..5ce8646
--- /dev/null
+++ b/src/declarative/util/qfxperf.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxperf.h"
+
+
+QT_BEGIN_NAMESPACE
+Q_DEFINE_PERFORMANCE_LOG(QFxPerf, "QFx") {
+ Q_DEFINE_PERFORMANCE_METRIC(XmlParsing, "XML Parsing");
+ Q_DEFINE_PERFORMANCE_METRIC(Compile, "XML Compilation");
+ Q_DEFINE_PERFORMANCE_METRIC(CompileRun, "XML Compilation Run");
+ Q_DEFINE_PERFORMANCE_METRIC(CssParsing, "CSS Parsing");
+ Q_DEFINE_PERFORMANCE_METRIC(CreateComponent, "Component creation");
+ Q_DEFINE_PERFORMANCE_METRIC(BindInit, "BindValue Initialization");
+ Q_DEFINE_PERFORMANCE_METRIC(BindCompile, "BindValue compile");
+ Q_DEFINE_PERFORMANCE_METRIC(BindValue, "BindValue execution");
+ Q_DEFINE_PERFORMANCE_METRIC(BindValueSSE, "BindValue execution SSE");
+ Q_DEFINE_PERFORMANCE_METRIC(BindValueQt, "BindValue execution QtScript");
+ Q_DEFINE_PERFORMANCE_METRIC(BindableValueUpdate, "QmlBindableValue::update");
+ Q_DEFINE_PERFORMANCE_METRIC(PixmapLoad, "Pixmap loading");
+ Q_DEFINE_PERFORMANCE_METRIC(MetaProperty, "Meta property resolution");
+ Q_DEFINE_PERFORMANCE_METRIC(PathCache, "Path cache");
+ Q_DEFINE_PERFORMANCE_METRIC(CreateParticle, "Particle creation");
+ Q_DEFINE_PERFORMANCE_METRIC(FontDatabase, "Font database creation");
+ Q_DEFINE_PERFORMANCE_METRIC(ItemComponentComplete, "QFxItem::componentComplete");
+ Q_DEFINE_PERFORMANCE_METRIC(ImageComponentComplete, "QFxImage::componentComplete");
+ Q_DEFINE_PERFORMANCE_METRIC(ComponentInstanceComponentComplete, "QFxComponentInstance::componentComplete");
+ Q_DEFINE_PERFORMANCE_METRIC(BaseLayoutComponentComplete, "QFxBaseLayout::componentComplete");
+ Q_DEFINE_PERFORMANCE_METRIC(TextComponentComplete, "QFxText::componentComplete");
+ Q_DEFINE_PERFORMANCE_METRIC(ContextQuery, "QtScript: Query Context");
+ Q_DEFINE_PERFORMANCE_METRIC(ContextProperty, "QtScript: Context Property");
+ Q_DEFINE_PERFORMANCE_METRIC(ObjectQuery, "QtScript: Query Object");
+ Q_DEFINE_PERFORMANCE_METRIC(ObjectProperty, "QtScript: Object Property");
+ Q_DEFINE_PERFORMANCE_METRIC(ObjectSetProperty, "QtScript: Set Object Property");
+ Q_DEFINE_PERFORMANCE_METRIC(QFxText_setText, "QFxText::setText");
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qfxperf.h b/src/declarative/util/qfxperf.h
new file mode 100644
index 0000000..b1f9bd0
--- /dev/null
+++ b/src/declarative/util/qfxperf.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef _QFXPERF_H_
+#define _QFXPERF_H_
+
+#include "qperformancelog.h"
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+Q_DECLARE_PERFORMANCE_LOG(QFxPerf) {
+ Q_DECLARE_PERFORMANCE_METRIC(XmlParsing);
+ Q_DECLARE_PERFORMANCE_METRIC(Compile);
+ Q_DECLARE_PERFORMANCE_METRIC(CompileRun);
+ Q_DECLARE_PERFORMANCE_METRIC(CssParsing);
+ Q_DECLARE_PERFORMANCE_METRIC(CreateComponent);
+ Q_DECLARE_PERFORMANCE_METRIC(BindInit);
+ Q_DECLARE_PERFORMANCE_METRIC(BindCompile);
+ Q_DECLARE_PERFORMANCE_METRIC(BindValue);
+ Q_DECLARE_PERFORMANCE_METRIC(BindValueSSE);
+ Q_DECLARE_PERFORMANCE_METRIC(BindValueQt);
+ Q_DECLARE_PERFORMANCE_METRIC(BindableValueUpdate);
+ Q_DECLARE_PERFORMANCE_METRIC(PixmapLoad);
+ Q_DECLARE_PERFORMANCE_METRIC(MetaProperty);
+ Q_DECLARE_PERFORMANCE_METRIC(PathCache);
+ Q_DECLARE_PERFORMANCE_METRIC(CreateParticle);
+ Q_DECLARE_PERFORMANCE_METRIC(FontDatabase);
+ Q_DECLARE_PERFORMANCE_METRIC(ItemComponentComplete);
+ Q_DECLARE_PERFORMANCE_METRIC(ImageComponentComplete);
+ Q_DECLARE_PERFORMANCE_METRIC(ComponentInstanceComponentComplete);
+ Q_DECLARE_PERFORMANCE_METRIC(BaseLayoutComponentComplete);
+ Q_DECLARE_PERFORMANCE_METRIC(TextComponentComplete);
+ Q_DECLARE_PERFORMANCE_METRIC(ContextQuery);
+ Q_DECLARE_PERFORMANCE_METRIC(ContextProperty);
+ Q_DECLARE_PERFORMANCE_METRIC(ObjectQuery);
+ Q_DECLARE_PERFORMANCE_METRIC(ObjectProperty);
+ Q_DECLARE_PERFORMANCE_METRIC(ObjectSetProperty);
+ Q_DECLARE_PERFORMANCE_METRIC(QFxText_setText);
+}
+
+#endif // _QFXPERF_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qfxview.cpp b/src/declarative/util/qfxview.cpp
new file mode 100644
index 0000000..e17decf
--- /dev/null
+++ b/src/declarative/util/qfxview.cpp
@@ -0,0 +1,514 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscriptvalueiterator.h"
+#include "qdebug.h"
+#include "qtimer.h"
+#include "qevent.h"
+#include "qdir.h"
+#include "qcoreapplication.h"
+#include "qfontdatabase.h"
+#include "qicon.h"
+#include "qurl.h"
+#include "qboxlayout.h"
+#include "qbasictimer.h"
+
+#include "qmlbindablevalue.h"
+#include "qml.h"
+#include "qfxitem.h"
+#include "qperformancelog.h"
+#include "qfxperf.h"
+
+#include "qfxview.h"
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmldebugger.h>
+
+
+QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(itemTreeDump, ITEMTREE_DUMP);
+DEFINE_BOOL_CONFIG_OPTION(qmlDebugger, QML_DEBUGGER);
+
+static QVariant stringToPixmap(const QString &str)
+{
+ //XXX need to use correct paths
+ return QVariant(QPixmap(str));
+}
+
+static QVariant stringToIcon(const QString &str)
+{
+ //XXX need to use correct paths
+ return QVariant(QIcon(str));
+}
+
+static QVariant stringToKeySequence(const QString &str)
+{
+ return QVariant::fromValue(QKeySequence(str));
+}
+
+static QVariant stringToUrl(const QString &str)
+{
+ return QVariant(QUrl(str));
+}
+
+class QFxViewPrivate
+{
+public:
+ QFxViewPrivate(QFxView *w)
+ : q(w), root(0), component(0) {}
+
+ QFxView *q;
+ QFxItem *root;
+
+ QUrl source;
+ QString qml;
+
+ QmlEngine engine;
+ QmlComponent *component;
+ QBasicTimer resizetimer;
+
+ QSize initialSize;
+
+ void init();
+};
+
+/*!
+ \class QFxView
+ \brief The QFxView class provides a widget for displaying a Qt Declarative user interface.
+
+ QFxView currently provides a minimal interface for displaying QML
+ files, and connecting between QML and C++ Qt objects.
+
+ Typical usage:
+ \code
+ ...
+ QFxView *view = new QFxView(this);
+ vbox->addWidget(view);
+
+ QUrl url(fileName);
+ view->setUrl(url);
+ ...
+ view->execute();
+ ...
+ \endcode
+*/
+
+/*!
+ \fn QFxView::QFxView(QWidget *parent)
+
+ Constructs a QFxView with the given \a parent.
+*/
+QFxView::QFxView(QWidget *parent)
+: QSimpleCanvas(parent), d(new QFxViewPrivate(this))
+{
+ setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
+ d->init();
+}
+
+/*!
+ \fn QFxView::QFxView(QSimpleCanvas::CanvasMode mode, QWidget *parent)
+ \internal
+ Constructs a QFxView with the given \a parent. The canvas
+ \a mode can be QSimpleCanvas::GraphicsView or
+ QSimpleCanvas::SimpleCanvas.
+*/
+QFxView::QFxView(QSimpleCanvas::CanvasMode mode, QWidget *parent)
+: QSimpleCanvas(mode, parent), d(new QFxViewPrivate(this))
+{
+ setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
+ d->init();
+}
+
+void QFxViewPrivate::init()
+{
+ // XXX: These need to be put in a central location for this kind of thing
+ qRegisterMetaType<QFxAnchorLine>("QFxAnchorLine");
+
+ QmlMetaType::registerCustomStringConverter(QVariant::Pixmap, &stringToPixmap);
+ QmlMetaType::registerCustomStringConverter(QVariant::Icon, &stringToIcon);
+ QmlMetaType::registerCustomStringConverter(QVariant::KeySequence, &stringToKeySequence);
+ QmlMetaType::registerCustomStringConverter(QVariant::Url, &stringToUrl);
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::FontDatabase> perf;
+#endif
+ QFontDatabase database;
+}
+
+/*!
+ The destructor clears the view's \l {QFxItem} {items} and
+ deletes the internal representation.
+
+ \sa clearItems()
+ */
+QFxView::~QFxView()
+{
+ clearItems();
+ delete d; d = 0;
+}
+
+/*!
+ Sets the source to the \a url. The QML string is set to
+ empty.
+ */
+void QFxView::setUrl(const QUrl& url)
+{
+ d->source = url;
+ d->qml = QString();
+}
+
+/*!
+ Sets the source to the URL from the \a filename, and sets
+ the QML string to \a qml.
+ */
+void QFxView::setQml(const QString &qml, const QString &filename)
+{
+ d->source = QUrl::fromLocalFile(filename);
+ d->qml = qml;
+}
+
+/*!
+ Returns the QML string.
+ */
+QString QFxView::qml() const
+{
+ return d->qml;
+}
+
+/*!
+ Returns a pointer to the QmlEngine used for instantiating
+ QML Components.
+ */
+QmlEngine* QFxView::engine()
+{
+ return &d->engine;
+}
+
+/*!
+ This function returns the root of the context hierarchy. Each QML
+ component is instantiated in a QmlContext. QmlContext's are
+ essential for passing data to QML components. In QML, contexts are
+ arranged hierarchically and this hierarchy is managed by the
+ QmlEngine.
+ */
+QmlContext* QFxView::rootContext()
+{
+ return d->engine.rootContext();
+}
+
+/*!
+ Displays the Qt Declarative user interface.
+*/
+void QFxView::execute()
+{
+ if (d->qml.isEmpty()) {
+ d->component = new QmlComponent(&d->engine, d->source, this);
+ } else {
+ d->component = new QmlComponent(&d->engine, d->qml.toUtf8(), d->source);
+ }
+
+ if (!d->component->isLoading()) {
+ continueExecute();
+ } else {
+ connect(d->component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(continueExecute()));
+ }
+}
+
+/*!
+ \internal
+*/
+void QFxView::printErrorLine(const QmlError &error)
+{
+ QUrl url = error.url();
+ if (error.line() > 0 && error.column() > 0 &&
+ url.scheme() == QLatin1String("file")) {
+ QString file = url.toLocalFile();
+ QFile f(file);
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray data = f.readAll();
+ QTextStream stream(data, QIODevice::ReadOnly);
+ const QString code = stream.readAll();
+ const QStringList lines = code.split(QLatin1Char('\n'));
+
+ if (lines.count() >= error.line()) {
+ const QString &line = lines.at(error.line() - 1);
+ qWarning() << qPrintable(line);
+
+ int column = qMax(0, error.column() - 1);
+ column = qMin(column, line.length());
+
+ QByteArray ind;
+ ind.reserve(column);
+ for (int i = 0; i < column; ++i) {
+ const QChar ch = line.at(i);
+ if (ch.isSpace())
+ ind.append(ch.unicode());
+ else
+ ind.append(' ');
+ }
+ ind.append('^');
+ qWarning() << ind.constData();
+ }
+ }
+ }
+}
+
+/*!
+ \internal
+ */
+void QFxView::continueExecute()
+{
+ disconnect(d->component, SIGNAL(statusChanged(QmlComponent::Status)), this, SLOT(continueExecute()));
+
+ if (!d->component){
+ qWarning() << "Error in loading" << d->source;
+ return;
+ }
+
+ if(d->component->isError()) {
+ QList<QmlError> errors = d->component->errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return;
+ }
+
+ QObject *obj = d->component->create();
+
+ if(d->component->isError()) {
+ QList<QmlError> errors = d->component->errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return;
+ }
+
+ if (obj) {
+ if (QFxItem *item = qobject_cast<QFxItem *>(obj)) {
+ item->QSimpleCanvasItem::setParent(QSimpleCanvas::root());
+
+ if (itemTreeDump())
+ item->dump();
+
+ if(qmlDebugger()) {
+ QmlDebugger *debugger = new QmlDebugger;
+ debugger->setDebugObject(item);
+ debugger->setCanvas(this);
+ debugger->show();
+ raise();
+ debugger->raise();
+ }
+
+ QPerformanceLog::displayData();
+ QPerformanceLog::clear();
+ d->root = item;
+ connect(item, SIGNAL(widthChanged()), this, SLOT(sizeChanged()));
+ connect(item, SIGNAL(heightChanged()), this, SLOT(sizeChanged()));
+ emit sceneResized(QSize(d->root->width(),d->root->height()));
+ } else if (QWidget *wid = qobject_cast<QWidget *>(obj)) {
+ window()->setAttribute(Qt::WA_OpaquePaintEvent, false);
+ window()->setAttribute(Qt::WA_NoSystemBackground, false);
+ if (!layout()) {
+ setLayout(new QVBoxLayout);
+ } else if (layout()->count()) {
+ // Hide the QGraphicsView in GV mode.
+ QLayoutItem *item = layout()->itemAt(0);
+ if (item->widget())
+ item->widget()->hide();
+ }
+ layout()->addWidget(wid);
+ emit sceneResized(wid->size());
+ }
+ }
+}
+
+/*! \fn void QFxView::sceneResized(QSize size)
+ This signal is emitted when the view is resized to \a size.
+ */
+
+/*!
+ \internal
+ */
+void QFxView::sizeChanged()
+{
+ // delay, so we catch both width and height changing.
+ d->resizetimer.start(0,this);
+}
+
+/*!
+ If the \l {QTimerEvent} {timer event} \a e is this
+ view's resize timer, sceneResized() is emitted.
+ */
+void QFxView::timerEvent(QTimerEvent* e)
+{
+ if (e->timerId() == d->resizetimer.timerId()) {
+ if (d->root)
+ emit sceneResized(QSize(d->root->width(),d->root->height()));
+ d->resizetimer.stop();
+ updateGeometry();
+ }
+}
+
+/*!
+ The size hint is the size of the root item.
+*/
+QSize QFxView::sizeHint() const
+{
+ if (d->initialSize.width() <= 0)
+ d->initialSize.setWidth(d->root->width());
+ if (d->initialSize.height() <= 0)
+ d->initialSize.setHeight(d->root->height());
+ return d->initialSize;
+}
+
+/*!
+ Creates a \l{QmlComponent} {component} from the \a qml
+ string, and returns it as an \l {QFxItem} {item}. If the
+ \a parent item is provided, it becomes the new item's
+ parent. \a parent should be in this view's item hierarchy.
+ */
+QFxItem* QFxView::addItem(const QString &qml, QFxItem* parent)
+{
+ if (!d->root)
+ return 0;
+
+ QmlComponent component(&d->engine, qml.toUtf8(), QUrl());
+ if(d->component->isError()) {
+ QList<QmlError> errors = d->component->errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return 0;
+ }
+
+ QObject *obj = component.create();
+ if(d->component->isError()) {
+ QList<QmlError> errors = d->component->errors();
+ foreach (const QmlError &error, errors) {
+ qWarning() << error;
+ }
+
+ return 0;
+ }
+
+ if (obj){
+ QFxItem *item = static_cast<QFxItem *>(obj);
+ if (!parent)
+ parent = d->root;
+
+ item->setItemParent(parent);
+ return item;
+ }
+ return 0;
+}
+
+/*!
+ Deletes the view's \l {QFxItem} {items} and the \l {QmlEngine}
+ {QML engine's} Component cache.
+ */
+void QFxView::reset()
+{
+ clearItems();
+ d->engine.clearComponentCache();
+}
+
+/*!
+ Deletes the view's \l {QFxItem} {items}.
+ */
+void QFxView::clearItems()
+{
+ if (!d->root)
+ return;
+ delete d->root;
+ d->root = 0;
+}
+
+/*!
+ Returns the view's root \l {QFxItem} {item}.
+ */
+QFxItem *QFxView::root() const
+{
+ return d->root;
+}
+
+/*!
+ This function handles the \l {QResizeEvent} {resize event}
+ \a e.
+ */
+void QFxView::resizeEvent(QResizeEvent *e)
+{
+ if (d->root) {
+ d->root->setWidth(width());
+ d->root->setHeight(height());
+ }
+ QSimpleCanvas::resizeEvent(e);
+}
+
+/*! \fn void QFxView::focusInEvent(QFocusEvent *e)
+ This virtual function does nothing with the event \a e
+ in this class.
+ */
+void QFxView::focusInEvent(QFocusEvent *)
+{
+ // Do nothing (do not call QWidget::update())
+}
+
+
+/*! \fn void QFxView::focusOutEvent(QFocusEvent *e)
+ This virtual function does nothing with the event \a e
+ in this class.
+ */
+void QFxView::focusOutEvent(QFocusEvent *)
+{
+ // Do nothing (do not call QWidget::update())
+}
+
+/*!
+ \internal
+ */
+void QFxView::dumpRoot()
+{
+ root()->dump();
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qfxview.h b/src/declarative/util/qfxview.h
new file mode 100644
index 0000000..d6f786c
--- /dev/null
+++ b/src/declarative/util/qfxview.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFXVIEW_H
+#define QFXVIEW_H
+
+#include <qfxglobal.h>
+#include <QtCore/qdatetime.h>
+#include <QtGui/qgraphicssceneevent.h>
+#include <QtGui/qwidget.h>
+#include <qsimplecanvas.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QFxItem;
+class QmlEngine;
+class QmlContext;
+class QmlError;
+
+class QFxViewPrivate;
+class Q_DECLARATIVE_EXPORT QFxView : public QSimpleCanvas
+{
+Q_OBJECT
+public:
+ explicit QFxView(QWidget *parent = 0);
+ QFxView(QSimpleCanvas::CanvasMode mode, QWidget* parent = 0);
+
+ virtual ~QFxView();
+
+ void setUrl(const QUrl&);
+ void setQml(const QString &qml, const QString &filename=QString());
+ QString qml() const;
+ QmlEngine* engine();
+ QmlContext* rootContext();
+ virtual void execute();
+ virtual void reset();
+
+ virtual QFxItem* addItem(const QString &qml, QFxItem* parent=0);
+ virtual void clearItems();
+
+ virtual QFxItem *root() const;
+
+ QSize sizeHint() const;
+
+ void dumpRoot();
+
+ static void printErrorLine(const QmlError &);
+Q_SIGNALS:
+ void sceneResized(QSize size);
+
+private Q_SLOTS:
+ void continueExecute();
+ void sizeChanged();
+
+protected:
+ virtual void resizeEvent(QResizeEvent *);
+ void focusInEvent(QFocusEvent *);
+ void focusOutEvent(QFocusEvent *);
+ void timerEvent(QTimerEvent*);
+
+private:
+ friend class QFxViewPrivate;
+ QFxViewPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXVIEW_H
diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp
new file mode 100644
index 0000000..dd4e1eb
--- /dev/null
+++ b/src/declarative/util/qmlanimation.cpp
@@ -0,0 +1,2259 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlanimation.h"
+#include "qvariant.h"
+#include "qcolor.h"
+#include "qfile.h"
+#include "qmlpropertyvaluesource.h"
+#include "qml.h"
+#include "qmlanimation_p.h"
+#include "qmlbehaviour.h"
+#include <QParallelAnimationGroup>
+#include <QSequentialAnimationGroup>
+#include <QtCore/qset.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qsize.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <private/qmlstringconverters_p.h>
+#include <private/qvariantanimation_p.h>
+
+/* TODO:
+ Check for any memory leaks
+ easing should be a QEasingCurve-type property
+ All other XXXs
+*/
+
+QT_BEGIN_NAMESPACE
+
+QEasingCurve stringToCurve(const QString &curve)
+{
+ QEasingCurve easingCurve;
+
+ QString normalizedCurve = curve;
+ bool hasParams = curve.contains(QLatin1Char('('));
+ QStringList props;
+
+ if (hasParams) {
+ QString easeName = curve.trimmed();
+ if (!easeName.endsWith(QLatin1Char(')'))) {
+ qWarning("QEasingCurve: Unmatched perenthesis in easing function '%s'",
+ curve.toLatin1().constData());
+ return easingCurve;
+ }
+
+ int idx = easeName.indexOf(QLatin1Char('('));
+ QString prop_str =
+ easeName.mid(idx + 1, easeName.length() - 1 - idx - 1);
+ normalizedCurve = easeName.left(idx);
+
+ props = prop_str.split(QLatin1Char(','));
+ }
+
+ normalizedCurve = normalizedCurve.mid(4);
+ //XXX optimize?
+ int index = QEasingCurve::staticMetaObject.indexOfEnumerator("Type");
+ QMetaEnum me = QEasingCurve::staticMetaObject.enumerator(index);
+
+ int value = me.keyToValue(normalizedCurve.toLatin1().constData());
+ if (value < 0) {
+ //XXX print line number
+ qWarning("QEasingCurve: Unknown easing curve '%s'",
+ curve.toLatin1().constData());
+ value = 0;
+ }
+ easingCurve.setType((QEasingCurve::Type)value);
+
+ if (hasParams) {
+ foreach(const QString &str, props) {
+ int sep = str.indexOf(QLatin1Char(':'));
+
+ if (sep == -1) {
+ qWarning("QEasingCurve: Improperly specified property in easing function '%s'",
+ curve.toLatin1().constData());
+ return easingCurve;
+ }
+
+ QString propName = str.left(sep).trimmed();
+ bool isOk;
+ qreal propValue = str.mid(sep + 1).trimmed().toDouble(&isOk);
+
+ if (propName.isEmpty() || !isOk) {
+ qWarning("QEasingCurve: Improperly specified property in easing function '%s'",
+ curve.toLatin1().constData());
+ return easingCurve;
+ }
+
+ //XXX optimize
+ if (propName == QLatin1String("amplitude")) {
+ easingCurve.setAmplitude(propValue);
+ } else if (propName == QLatin1String("period")) {
+ easingCurve.setPeriod(propValue);
+ } else if (propName == QLatin1String("overshoot")) {
+ easingCurve.setOvershoot(propValue);
+ }
+ }
+ }
+
+ return easingCurve;
+}
+
+QML_DEFINE_NOCREATE_TYPE(QmlAbstractAnimation);
+
+/*!
+ \qmlclass Animation
+ \brief The Animation element is the base of all QML animations.
+
+ The Animation element cannot be used directly in a QML file. It exists
+ to provide a set of common properties and methods, available across all the
+ other animation types that inherit from it. Attempting to use the Animation
+ element directly will result in an error.
+*/
+
+/*!
+ \class QmlAbstractAnimation
+ \internal
+*/
+
+QmlAbstractAnimation::QmlAbstractAnimation(QObject *parent)
+: QmlPropertyValueSource(*(new QmlAbstractAnimationPrivate), parent)
+{
+}
+
+QmlAbstractAnimation::~QmlAbstractAnimation()
+{
+}
+
+QmlAbstractAnimation::QmlAbstractAnimation(QmlAbstractAnimationPrivate &dd, QObject *parent)
+: QmlPropertyValueSource(dd, parent)
+{
+}
+
+/*!
+ \qmlproperty bool Animation::running
+ This property holds whether the animation is currently running.
+
+ The \c running property can be set to declaratively control whether or not
+ an animation is running. The following example will animate a rectangle
+ whenever the \l MouseRegion is pressed.
+
+ \code
+ Rect {
+ width: 100; height: 100
+ x: NumericAnimation {
+ running: MyMouse.pressed
+ from: 0; to: 100
+ }
+ MouseRegion { id: MyMouse }
+ }
+ \endcode
+
+ Likewise, the \c running property can be read to determine if the animation
+ is running. In the following example the text element will indicate whether
+ or not the animation is running.
+
+ \code
+ NumericAnimation { id: MyAnimation }
+ Text { text: MyAnimation.running ? "Animation is running" : "Animation is not running" }
+ \endcode
+
+ Animations can also be started and stopped imperatively from JavaScript
+ using the \c start() and \c stop() methods.
+
+ By default, animations are not running.
+*/
+bool QmlAbstractAnimation::isRunning() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->running;
+}
+
+void QmlAbstractAnimationPrivate::commence()
+{
+ Q_Q(QmlAbstractAnimation);
+
+ q->prepare(userProperty.value);
+ q->qtAnimation()->start();
+ if (q->qtAnimation()->state() != QAbstractAnimation::Running) {
+ running = false;
+ emit q->completed();
+ }
+}
+
+void QmlAbstractAnimation::setRunning(bool r)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->running == r)
+ return;
+
+ if (d->group) {
+ qWarning("QmlAbstractAnimation: setRunning() cannot be used on non-root animation nodes");
+ return;
+ }
+
+ d->running = r;
+ if (d->running) {
+ if (!d->connectedTimeLine) {
+ QObject::connect(qtAnimation(), SIGNAL(finished()),
+ this, SLOT(timelineComplete()));
+ d->connectedTimeLine = true;
+ }
+ if (d->componentComplete)
+ d->commence();
+ else
+ d->startOnCompletion = true;
+ emit started();
+ } else {
+ if (!d->finishPlaying)
+ qtAnimation()->stop();
+ emit completed();
+ }
+
+ emit runningChanged(d->running);
+}
+
+void QmlAbstractAnimation::classBegin()
+{
+ Q_D(QmlAbstractAnimation);
+ d->componentComplete = false;
+}
+
+void QmlAbstractAnimation::componentComplete()
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->startOnCompletion)
+ d->commence();
+ d->componentComplete = true;
+}
+
+/*!
+ \qmlproperty bool Animation::finishPlaying
+ This property holds whether the animation should finish playing when it is stopped.
+
+ If this true the animation will complete its current iteration when it
+ is stopped - either by setting the \c running property to false, or by
+ calling the \c stop() method. The \c complete() method is not effected
+ by this value.
+
+ This behaviour is most useful when the \c repeat property is set, as the
+ animation will finish playing normally but not restart.
+
+ By default, the finishPlaying property is not set.
+*/
+bool QmlAbstractAnimation::finishPlaying() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->finishPlaying;
+}
+
+void QmlAbstractAnimation::setFinishPlaying(bool f)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->finishPlaying == f)
+ return;
+
+ d->finishPlaying = f;
+ emit finishPlayingChanged(f);
+}
+
+/*!
+ \qmlproperty bool Animation::repeat
+ This property holds whether the animation should repeat.
+
+ If set, the animation will continuously repeat until it is explicitly
+ stopped - either by setting the \c running property to false, or by calling
+ the \c stop() method.
+
+ In the following example, the rectangle will spin indefinately.
+
+ \code
+ Rect {
+ rotation: NumericAnimation { running: true; repeat: true; from: 0 to: 360 }
+ }
+ \endcode
+*/
+bool QmlAbstractAnimation::repeat() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->repeat;
+}
+
+void QmlAbstractAnimation::setRepeat(bool r)
+{
+ Q_D(QmlAbstractAnimation);
+ if (r == d->repeat)
+ return;
+
+ d->repeat = r;
+ int lc = r ? -1 : 1;
+ qtAnimation()->setLoopCount(lc);
+ emit repeatChanged(r);
+}
+
+QmlAnimationGroup *QmlAbstractAnimation::group() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->group;
+}
+
+void QmlAbstractAnimation::setGroup(QmlAnimationGroup *g)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->group == g)
+ return;
+ if (d->group)
+ static_cast<QmlAnimationGroupPrivate *>(d->group->d_ptr)->animations.removeAll(this);
+
+ d->group = g;
+
+ if (d->group && !static_cast<QmlAnimationGroupPrivate *>(d->group->d_ptr)->animations.contains(this))
+ static_cast<QmlAnimationGroupPrivate *>(d->group->d_ptr)->animations.append(this);
+
+ if (d->group)
+ ((QAnimationGroup*)d->group->qtAnimation())->addAnimation(qtAnimation());
+
+ //if (g) //if removed from a group, then the group should no longer be the parent
+ setParent(g);
+}
+
+/*!
+ \qmlproperty Object Animation::target
+ This property holds an explicit target object to animate.
+
+ The exact effect of the \c target property depends on how the animation
+ is being used. Refer to the \l animation documentation for details.
+*/
+QObject *QmlAbstractAnimation::target() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->target;
+}
+
+void QmlAbstractAnimation::setTarget(QObject *o)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->target == o)
+ return;
+
+ d->target = o;
+ if (d->target && !d->propertyName.isEmpty()) {
+ d->userProperty = QmlMetaProperty(d->target, d->propertyName);
+ } else {
+ d->userProperty.invalidate();
+ }
+
+ emit targetChanged(d->target, d->propertyName);
+}
+
+/*!
+ \qmlproperty string Animation::property
+ This property holds an explicit property to animated.
+
+ The exact effect of the \c property property depends on how the animation
+ is being used. Refer to the \l animation documentation for details.
+*/
+QString QmlAbstractAnimation::property() const
+{
+ Q_D(const QmlAbstractAnimation);
+ return d->propertyName;
+}
+
+void QmlAbstractAnimation::setProperty(const QString &n)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->propertyName == n)
+ return;
+
+ d->propertyName = n;
+ if (d->target && !d->propertyName.isEmpty()) {
+ d->userProperty = QmlMetaProperty(d->target, d->propertyName);
+ } else {
+ d->userProperty.invalidate();
+ }
+
+ emit targetChanged(d->target, d->propertyName);
+}
+
+/*!
+ \qmlmethod Animation::start()
+ \brief Starts the animation.
+
+ If the animation is already running, calling this method has no effect. The
+ \c running property will be true following a call to \c start().
+*/
+void QmlAbstractAnimation::start()
+{
+ setRunning(true);
+}
+
+/*!
+ \qmlmethod Animation::stop()
+ \brief Stops the animation.
+
+ If the animation is not running, calling this method has no effect. The
+ \c running property will be false following a call to \c stop().
+
+ Normally \c stop() stops the animation immediately, and the animation has
+ no further influence on property values. In this example animation
+ \code
+ Rect {
+ x: NumericAnimation { from: 0; to: 100; duration: 500 }
+ }
+ \endcode
+ was stopped at time 250ms, the \c x property will have a value of 50.
+
+ However, if the \c finishPlaying property is set, the animation will
+ continue running until it completes and then stop. The \c running property
+ will still become false immediately.
+*/
+void QmlAbstractAnimation::stop()
+{
+ setRunning(false);
+}
+
+/*!
+ \qmlmethod Animation::restart()
+ \brief Restarts the animation.
+
+ This is a convenience method, and is equivalent to calling \c stop() and
+ then \c start().
+*/
+void QmlAbstractAnimation::restart()
+{
+ stop();
+ start();
+}
+
+/*!
+ \qmlmethod Animation::complete()
+ \brief Stops the animation, jumping to the final property values.
+
+ If the animation is not running, calling this method has no effect. The
+ \c running property will be false following a call to \c complete().
+
+ Unlike \c stop(), \c complete() immediately fast-forwards the animation to
+ its end. In the following example,
+ \code
+ Rect {
+ x: NumericAnimation { from: 0; to: 100; duration: 500 }
+ }
+ \endcode
+ calling \c stop() at time 250ms will result in the \c x property having
+ a value of 50, while calling \c complete() will set the \c x property to
+ 100, exactly as though the animation had played the whole way through.
+*/
+void QmlAbstractAnimation::complete()
+{
+ if (isRunning()) {
+ qtAnimation()->setCurrentTime(qtAnimation()->duration());
+ }
+}
+
+void QmlAbstractAnimation::setTarget(const QmlMetaProperty &p)
+{
+ Q_D(QmlAbstractAnimation);
+ if (d->userProperty.isNull)
+ d->userProperty = p;
+}
+
+//prepare is called before an animation begins
+//(when an animation is used as a simple animation, and not as part of a transition)
+void QmlAbstractAnimation::prepare(QmlMetaProperty &)
+{
+}
+
+void QmlAbstractAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_UNUSED(actions);
+ Q_UNUSED(modified);
+ Q_UNUSED(direction);
+}
+
+void QmlAbstractAnimation::timelineComplete()
+{
+ setRunning(false);
+}
+
+/*!
+ \qmlclass PauseAnimation QmlPauseAnimation
+ \inherits Animation
+ \brief The PauseAnimation provides a pause for an animation.
+
+ When used in a SequentialAnimation, PauseAnimation is a step when
+ nothing happens, for a specified duration.
+
+ A 500ms animation sequence, with a 100ms pause between two animations:
+ \code
+ SequentialAnimation {
+ NumericAnimation { ... duration: 200 }
+ PauseAnimation { duration: 100 }
+ NumericAnimation { ... duration: 200 }
+ }
+ \endcode
+*/
+/*!
+ \internal
+ \class QmlPauseAnimation
+ \ingroup group_animation
+ \ingroup group_states
+ \brief The QmlPauseAnimation class provides a pause for an animation.
+
+ When used in a QmlSequentialAnimation, QmlPauseAnimation is a step when
+ nothing happens, for a specified duration.
+
+ A QmlPauseAnimation object can be instantiated in Qml using the tag
+ \l{xmlPauseAnimation} {&lt;PauseAnimation&gt;}.
+*/
+
+QML_DEFINE_TYPE(QmlPauseAnimation,PauseAnimation);
+QmlPauseAnimation::QmlPauseAnimation(QObject *parent)
+: QmlAbstractAnimation(*(new QmlPauseAnimationPrivate), parent)
+{
+ Q_D(QmlPauseAnimation);
+ d->init();
+}
+
+QmlPauseAnimation::~QmlPauseAnimation()
+{
+}
+
+void QmlPauseAnimationPrivate::init()
+{
+ Q_Q(QmlPauseAnimation);
+ pa = new QPauseAnimation(q);
+}
+
+/*!
+ \qmlproperty int PauseAnimation::duration
+ This property holds the duration of the pause in milliseconds
+
+ The default value is 250.
+*/
+/*!
+ \property QmlPauseAnimation::duration
+ \brief the duration of the pause in milliseconds
+
+ The default value is 250.
+*/
+int QmlPauseAnimation::duration() const
+{
+ Q_D(const QmlPauseAnimation);
+ return d->pa->duration();
+}
+
+void QmlPauseAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qWarning("QmlPauseAnimation: Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QmlPauseAnimation);
+ if (d->pa->duration() == duration)
+ return;
+ d->pa->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+void QmlPauseAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlPauseAnimation);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+}
+
+QAbstractAnimation *QmlPauseAnimation::qtAnimation()
+{
+ Q_D(QmlPauseAnimation);
+ return d->pa;
+}
+
+/*!
+ \qmlclass ColorAnimation QmlColorAnimation
+ \inherits Animation
+ \brief The ColorAnimation allows you to animate color changes.
+
+ \code
+ ColorAnimation { from: "white"; to: "#c0c0c0"; duration: 100 }
+ \endcode
+
+ The default property animated is \c color, but like other animations,
+ this can be changed by setting \c property. The \c color property will
+ still animate. XXX is this a bug?
+*/
+/*!
+ \internal
+ \class QmlColorAnimation
+ \ingroup group_animation
+ \ingroup group_states
+ \brief The QmlColorAnimation class allows you to animate color changes.
+
+ A QmlColorAnimation object can be instantiated in Qml using the tag
+ \l{xmlColorAnimation} {&lt;ColorAnimation&gt;}.
+*/
+
+QmlColorAnimation::QmlColorAnimation(QObject *parent)
+: QmlAbstractAnimation(*(new QmlColorAnimationPrivate), parent)
+{
+ Q_D(QmlColorAnimation);
+ d->init();
+}
+
+QmlColorAnimation::~QmlColorAnimation()
+{
+}
+
+void QmlColorAnimationPrivate::init()
+{
+ Q_Q(QmlColorAnimation);
+ ca = new QmlTimeLineValueAnimator(q);
+ ca->setStartValue(QVariant(0.0f));
+ ca->setEndValue(QVariant(1.0f));
+}
+
+/*!
+ \qmlproperty int ColorAnimation::duration
+ This property holds the duration of the color transition, in milliseconds.
+
+ The default value is 250.
+*/
+/*!
+ \property QmlColorAnimation::duration
+ \brief the duration of the transition, in milliseconds.
+
+ The default value is 250.
+*/
+int QmlColorAnimation::duration() const
+{
+ Q_D(const QmlColorAnimation);
+ return d->ca->duration();
+}
+
+void QmlColorAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qWarning("QmlColorAnimation: Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QmlColorAnimation);
+ if (d->ca->duration() == duration)
+ return;
+ d->ca->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+/*!
+ \qmlproperty color ColorAnimation::from
+ This property holds the starting color.
+*/
+/*!
+ \property QmlColorAnimation::from
+ \brief the starting color.
+*/
+QColor QmlColorAnimation::from() const
+{
+ Q_D(const QmlColorAnimation);
+ return d->fromValue;
+}
+
+void QmlColorAnimation::setFrom(const QColor &f)
+{
+ Q_D(QmlColorAnimation);
+ if (d->fromIsDefined && f == d->fromValue)
+ return;
+ d->fromValue = f;
+ d->fromIsDefined = f.isValid();
+ emit fromChanged(f);
+}
+
+/*!
+ \qmlproperty color ColorAnimation::from
+ This property holds the ending color.
+*/
+/*!
+ \property QmlColorAnimation::to
+ \brief the ending color.
+*/
+QColor QmlColorAnimation::to() const
+{
+ Q_D(const QmlColorAnimation);
+ return d->toValue;
+}
+
+void QmlColorAnimation::setTo(const QColor &t)
+{
+ Q_D(QmlColorAnimation);
+ if (d->toIsDefined && t == d->toValue)
+ return;
+ d->toValue = t;
+ d->toIsDefined = t.isValid();
+ emit toChanged(t);
+}
+
+/*!
+ \qmlproperty string ColorAnimation::easing
+ This property holds the easing curve used for the transition.
+
+ Each channel of the color is eased using the same easing curve.
+ See NumericAnimation::easing for a full discussion of easing,
+ and a list of available curves.
+*/
+QString QmlColorAnimation::easing() const
+{
+ Q_D(const QmlColorAnimation);
+ return d->easing;
+}
+
+void QmlColorAnimation::setEasing(const QString &e)
+{
+ Q_D(QmlColorAnimation);
+ if (d->easing == e)
+ return;
+
+ d->easing = e;
+ d->ca->setEasingCurve(stringToCurve(d->easing));
+ emit easingChanged(e);
+}
+
+/*!
+ \qmlproperty list<Item> ColorAnimation::filter
+ This property holds the items selected to be affected by this animation (all if not set).
+ \sa exclude
+*/
+QList<QObject *> *QmlColorAnimation::filter()
+{
+ Q_D(QmlColorAnimation);
+ return &d->filter;
+}
+
+/*!
+ \qmlproperty list<Item> ColorAnimation::exclude
+ This property holds the items not to be affected by this animation.
+ \sa filter
+*/
+QList<QObject *> *QmlColorAnimation::exclude()
+{
+ Q_D(QmlColorAnimation);
+ return &d->exclude;
+}
+
+void QmlColorAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlColorAnimation);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+ d->fromSourced = false;
+ d->value.QmlTimeLineValue::setValue(0.);
+ d->ca->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped);
+ d->ca->setFromSourcedValue(&d->fromSourced);
+}
+
+QAbstractAnimation *QmlColorAnimation::qtAnimation()
+{
+ Q_D(QmlColorAnimation);
+ return d->ca;
+}
+
+void QmlColorAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlColorAnimation);
+ Q_UNUSED(direction);
+
+ struct NTransitionData : public QmlTimeLineValue
+ {
+ QmlStateActions actions;
+ void write(QmlMetaProperty &property, const QVariant &color)
+ {
+ if (property.propertyType() == QVariant::Color) {
+ property.write(color);
+ }
+ }
+
+ void setValue(qreal v)
+ {
+ QmlTimeLineValue::setValue(v);
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QColor to(action.toValue.value<QColor>());
+
+ if (v == 1.) {
+ write(action.property, to);
+ } else {
+ if (action.fromValue.isNull()) {
+ action.fromValue = action.property.read();
+ if (action.fromValue.isNull())
+ action.fromValue = QVariant(QColor());
+ }
+
+ QColor from(action.fromValue.value<QColor>());
+
+ QVariant newColor = QmlColorAnimationPrivate::colorInterpolator(&from, &to, v);
+ write(action.property, newColor);
+ }
+ }
+ }
+ };
+
+ //XXX should we get rid of this?
+ QStringList props;
+ props << QLatin1String("color");
+ if (!d->propertyName.isEmpty() && !props.contains(d->propertyName))
+ props.append(d->propertyName);
+
+ NTransitionData *data = new NTransitionData;
+
+ QSet<QObject *> objs;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+
+ if ((d->filter.isEmpty() || d->filter.contains(obj)) &&
+ (!d->exclude.contains(obj)) && props.contains(propertyName) &&
+ (!target() || target() == obj)) {
+ objs.insert(obj);
+ Action myAction = action;
+
+ if (d->fromIsDefined) {
+ myAction.fromValue = QVariant(d->fromValue);
+ } else {
+ myAction.fromValue = QVariant();
+ }
+ if (d->toIsDefined)
+ myAction.toValue = QVariant(d->toValue);
+
+ modified << action.property;
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+
+ if (d->toValue.isValid() && target() && !objs.contains(target())) {
+ QObject *obj = target();
+ for (int jj = 0; jj < props.count(); ++jj) {
+ Action myAction;
+ myAction.property = QmlMetaProperty(obj, props.at(jj));
+
+ if (d->fromIsDefined)
+ myAction.fromValue = QVariant(d->fromValue);
+
+ myAction.toValue = QVariant(d->toValue);
+ myAction.bv = 0;
+ myAction.event = 0;
+ data->actions << myAction;
+ }
+ }
+
+ if (data->actions.count())
+ d->ca->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
+ else
+ delete data;
+}
+
+QVariantAnimation::Interpolator QmlColorAnimationPrivate::colorInterpolator = 0;
+
+void QmlColorAnimationPrivate::valueChanged(qreal v)
+{
+ if (!fromSourced) {
+ if (!fromIsDefined) {
+ fromValue = qvariant_cast<QColor>(property.read());
+ }
+ fromSourced = true;
+ }
+
+ if (property.propertyType() == QVariant::Color) {
+ QVariant newColor = colorInterpolator(&fromValue, &toValue, v);
+ property.write(newColor);
+ }
+}
+QML_DEFINE_TYPE(QmlColorAnimation,ColorAnimation);
+
+/*!
+ \qmlclass RunScriptAction QmlRunScriptAction
+ \inherits Animation
+ \brief The RunScripAction allows scripts to be run during transitions.
+
+*/
+/*!
+ \internal
+ \class QmlRunScriptAction
+ \brief The QmlRunScriptAction class allows scripts to be run during transitions
+
+ \sa xmlRunScriptAction
+*/
+QmlRunScriptAction::QmlRunScriptAction(QObject *parent)
+ :QmlAbstractAnimation(*(new QmlRunScriptActionPrivate), parent)
+{
+ Q_D(QmlRunScriptAction);
+ d->init();
+}
+
+QmlRunScriptAction::~QmlRunScriptAction()
+{
+}
+
+void QmlRunScriptActionPrivate::init()
+{
+ Q_Q(QmlRunScriptAction);
+ rsa = new QActionAnimation(&proxy, q);
+}
+
+/*!
+ \qmlproperty QString RunScript::script
+ This property holds the script to run.
+*/
+QString QmlRunScriptAction::script() const
+{
+ Q_D(const QmlRunScriptAction);
+ return d->script;
+}
+
+void QmlRunScriptAction::setScript(const QString &script)
+{
+ Q_D(QmlRunScriptAction);
+ if (script == d->script)
+ return;
+ d->script = script;
+ emit scriptChanged(script);
+}
+
+/*!
+ \qmlproperty QString RunScript::script
+ This property holds the file containing the script to run.
+*/
+QString QmlRunScriptAction::file() const
+{
+ Q_D(const QmlRunScriptAction);
+ return d->file;
+}
+
+void QmlRunScriptAction::setFile(const QString &file)
+{
+ Q_D(QmlRunScriptAction);
+ if (file == d->file)
+ return;
+ d->file = file;
+ emit fileChanged(file);
+}
+
+void QmlRunScriptActionPrivate::execute()
+{
+ Q_Q(QmlRunScriptAction);
+ QString scriptStr = script;
+ if (!file.isEmpty()){
+ QFile scriptFile(file);
+ if (scriptFile.open(QIODevice::ReadOnly | QIODevice::Text)){
+ scriptStr = QString::fromUtf8(scriptFile.readAll());
+ }
+ }
+
+ if (!scriptStr.isEmpty()) {
+ QmlExpression expr(qmlContext(q), scriptStr, q);
+ expr.setTrackChange(false);
+ expr.value();
+ }
+}
+
+QAbstractAnimation *QmlRunScriptAction::qtAnimation()
+{
+ Q_D(QmlRunScriptAction);
+ return d->rsa;
+}
+
+QML_DEFINE_TYPE(QmlRunScriptAction, RunScriptAction);
+
+/*!
+ \qmlclass SetPropertyAction QmlSetPropertyAction
+ \inherits Animation
+ \brief The SetPropertyAction allows property changes during transitions.
+
+ Explicitly set \c theimage.smooth=true during a transition:
+ \code
+ SetPropertyAction { target: theimage; property: "smooth"; value: true }
+ \endcode
+
+ Set \c thewebview.url to the value set for the destination state:
+ \code
+ SetPropertyAction { target: thewebview; property: "url" }
+ \endcode
+
+ The SetPropertyAction is immediate -
+ the target property is not animated to the selected value in any way.
+*/
+/*!
+ \internal
+ \class QmlSetPropertyAction
+ \brief The QmlSetPropertyAction class allows property changes during transitions.
+
+ A QmlSetPropertyAction object can be instantiated in Qml using the tag
+ \l{xmlSetPropertyAction} {&lt;SetPropertyAction&gt;}.
+*/
+QmlSetPropertyAction::QmlSetPropertyAction(QObject *parent)
+: QmlAbstractAnimation(*(new QmlSetPropertyActionPrivate), parent)
+{
+ Q_D(QmlSetPropertyAction);
+ d->init();
+}
+
+QmlSetPropertyAction::~QmlSetPropertyAction()
+{
+}
+
+void QmlSetPropertyActionPrivate::init()
+{
+ Q_Q(QmlSetPropertyAction);
+ spa = new QActionAnimation(q);
+}
+
+/*!
+ \qmlproperty string SetPropertyAction::properties
+ This property holds the properties to be immediately set, comma-separated.
+*/
+QString QmlSetPropertyAction::properties() const
+{
+ Q_D(const QmlSetPropertyAction);
+ return d->properties;
+}
+
+void QmlSetPropertyAction::setProperties(const QString &p)
+{
+ Q_D(QmlSetPropertyAction);
+ if (d->properties == p)
+ return;
+ d->properties = p;
+ emit propertiesChanged(p);
+}
+
+/*!
+ \qmlproperty list<Item> SetPropertyAction::filter
+ This property holds the items selected to be affected by this animation (all if not set).
+ \sa exclude
+*/
+QList<QObject *> *QmlSetPropertyAction::filter()
+{
+ Q_D(QmlSetPropertyAction);
+ return &d->filter;
+}
+
+/*!
+ \qmlproperty list<Item> SetPropertyAction::exclude
+ This property holds the items not to be affected by this animation.
+ \sa filter
+*/
+QList<QObject *> *QmlSetPropertyAction::exclude()
+{
+ Q_D(QmlSetPropertyAction);
+ return &d->exclude;
+}
+
+/*!
+ \qmlproperty any SetPropertyAction::value
+ This property holds the value to be set on the property.
+ If not set, then the value defined for the end state of the transition.
+*/
+QVariant QmlSetPropertyAction::value() const
+{
+ Q_D(const QmlSetPropertyAction);
+ return d->value;
+}
+
+void QmlSetPropertyAction::setValue(const QVariant &v)
+{
+ Q_D(QmlSetPropertyAction);
+ if (d->value.isNull || d->value != v) {
+ d->value = v;
+ emit valueChanged(v);
+ }
+}
+
+void QmlSetPropertyActionPrivate::doAction()
+{
+ property.write(value);
+}
+
+QAbstractAnimation *QmlSetPropertyAction::qtAnimation()
+{
+ Q_D(QmlSetPropertyAction);
+ return d->spa;
+}
+
+void QmlSetPropertyAction::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlSetPropertyAction);
+
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ d->spa->setAnimAction(&d->proxy, QAbstractAnimation::KeepWhenStopped);
+}
+
+void QmlSetPropertyAction::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlSetPropertyAction);
+ Q_UNUSED(direction);
+
+ struct QmlSetPropertyAnimationAction : public QAbstractAnimationAction
+ {
+ QmlStateActions actions;
+ virtual void doAction()
+ {
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ const Action &action = actions.at(ii);
+ QmlBehaviour::_ignore = true;
+ action.property.write(action.toValue);
+ QmlBehaviour::_ignore = false;
+ }
+ }
+ };
+
+ QStringList props = d->properties.split(QLatin1Char(','));
+ for (int ii = 0; ii < props.count(); ++ii)
+ props[ii] = props.at(ii).trimmed();
+ if (!d->propertyName.isEmpty() && !props.contains(d->propertyName))
+ props.append(d->propertyName);
+
+ QmlSetPropertyAnimationAction *data = new QmlSetPropertyAnimationAction;
+
+ QSet<QObject *> objs;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+
+ if ((d->filter.isEmpty() || d->filter.contains(obj)) &&
+ (!d->exclude.contains(obj)) && props.contains(propertyName) &&
+ (!target() || target() == obj)) {
+ objs.insert(obj);
+ Action myAction = action;
+
+ if (d->value.isValid())
+ myAction.toValue = d->value;
+
+ modified << action.property;
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+
+ if (d->value.isValid() && target() && !objs.contains(target())) {
+ QObject *obj = target();
+ for (int jj = 0; jj < props.count(); ++jj) {
+ Action myAction;
+ myAction.property = QmlMetaProperty(obj, props.at(jj));
+ myAction.toValue = d->value;
+ data->actions << myAction;
+ }
+ }
+
+ if (data->actions.count()) {
+ d->spa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ delete data;
+ }
+}
+
+QML_DEFINE_TYPE(QmlSetPropertyAction,SetPropertyAction);
+
+/*!
+ \qmlclass ParentChangeAction QmlParentChangeAction
+ \inherits Animation
+ \brief The ParentChangeAction allows parent changes during transitions.
+
+ The ParentChangeAction is immediate - it is not animated in any way.
+*/
+
+QmlParentChangeAction::QmlParentChangeAction(QObject *parent)
+: QmlAbstractAnimation(*(new QmlParentChangeActionPrivate), parent)
+{
+ Q_D(QmlParentChangeAction);
+ d->init();
+}
+
+QmlParentChangeAction::~QmlParentChangeAction()
+{
+}
+
+void QmlParentChangeActionPrivate::init()
+{
+ Q_Q(QmlParentChangeAction);
+ cpa = new QActionAnimation(q);
+}
+
+void QmlParentChangeActionPrivate::doAction()
+{
+ //XXX property.write(value);
+}
+
+void QmlParentChangeAction::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlParentChangeAction);
+
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ //XXX
+}
+
+QAbstractAnimation *QmlParentChangeAction::qtAnimation()
+{
+ Q_D(QmlParentChangeAction);
+ return d->cpa;
+}
+
+void QmlParentChangeAction::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlParentChangeAction);
+ Q_UNUSED(direction);
+
+ struct QmlParentChangeActionData : public QAbstractAnimationAction
+ {
+ QmlStateActions actions;
+ virtual void doAction()
+ {
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ const Action &action = actions.at(ii);
+ QmlBehaviour::_ignore = true;
+ action.property.write(action.toValue);
+ QmlBehaviour::_ignore = false;
+ }
+ }
+ };
+
+ QmlParentChangeActionData *data = new QmlParentChangeActionData;
+
+ QSet<QObject *> objs;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+
+ if ((!target() || target() == obj) && propertyName == QString(QLatin1String("moveToParent"))) {
+ objs.insert(obj);
+ Action myAction = action;
+
+ /*if (d->value.isValid())
+ myAction.toValue = d->value;*/
+
+ modified << action.property;
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+
+ /*if (d->value.isValid() && target() && !objs.contains(target())) {
+ QObject *obj = target();
+ for (int jj = 0; jj < props.count(); ++jj) {
+ Action myAction;
+ myAction.property = QmlMetaProperty(obj, props.at(jj));
+ myAction.toValue = d->value;
+ data->actions << myAction;
+ }
+ }*/
+
+ if (data->actions.count()) {
+ d->cpa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ delete data;
+ }
+}
+
+QML_DEFINE_TYPE(QmlParentChangeAction,ParentChangeAction);
+
+/*!
+ \qmlclass NumericAnimation QmlNumericAnimation
+ \inherits Animation
+ \brief The NumericAnimation allows you to animate changes in properties of type qreal.
+
+ Animate a set of properties over 200ms, from their values in the start state to
+ their values in the end state of the transition:
+ \code
+ NumericAnimation { properties: "x,y,scale"; duration: 200 }
+ \endcode
+*/
+
+/*!
+ \internal
+ \class QmlNumericAnimation
+ \ingroup group_animation
+ \ingroup group_states
+ \brief The QmlNumericAnimation class allows you to animate changes in properties of type qreal.
+
+ A QmlNumericAnimation object can be instantiated in Qml using the tag
+ \l{xmlNumericAnimation} {&lt;NumericAnimation&gt;}.
+*/
+
+QmlNumericAnimation::QmlNumericAnimation(QObject *parent)
+: QmlAbstractAnimation(*(new QmlNumericAnimationPrivate), parent)
+{
+ Q_D(QmlNumericAnimation);
+ d->init();
+}
+
+QmlNumericAnimation::~QmlNumericAnimation()
+{
+}
+
+void QmlNumericAnimationPrivate::init()
+{
+ Q_Q(QmlNumericAnimation);
+ na = new QmlTimeLineValueAnimator(q);
+ na->setStartValue(QVariant(0.0f));
+ na->setEndValue(QVariant(1.0f));
+}
+
+/*!
+ \qmlproperty int NumericAnimation::duration
+ This property holds the duration of the transition, in milliseconds.
+
+ The default value is 250.
+*/
+/*!
+ \property QmlNumericAnimation::duration
+ \brief the duration of the transition, in milliseconds.
+
+ The default value is 250.
+*/
+int QmlNumericAnimation::duration() const
+{
+ Q_D(const QmlNumericAnimation);
+ return d->na->duration();
+}
+
+void QmlNumericAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qWarning("QmlNumericAnimation: Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QmlNumericAnimation);
+ if (d->na->duration() == duration)
+ return;
+ d->na->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+/*!
+ \qmlproperty real NumericAnimation::from
+ This property holds the starting value.
+ If not set, then the value defined in the start state of the transition.
+*/
+/*!
+ \property QmlNumericAnimation::from
+ \brief the starting value.
+*/
+qreal QmlNumericAnimation::from() const
+{
+ Q_D(const QmlNumericAnimation);
+ return d->from;
+}
+
+void QmlNumericAnimation::setFrom(qreal f)
+{
+ Q_D(QmlNumericAnimation);
+ if (!d->from.isNull && f == d->from)
+ return;
+ d->from = f;
+ emit fromChanged(f);
+}
+
+/*!
+ \qmlproperty real NumericAnimation::to
+ This property holds the ending value.
+ If not set, then the value defined in the end state of the transition.
+*/
+/*!
+ \property QmlNumericAnimation::to
+ \brief the ending value.
+*/
+qreal QmlNumericAnimation::to() const
+{
+ Q_D(const QmlNumericAnimation);
+ return d->to;
+}
+
+void QmlNumericAnimation::setTo(qreal t)
+{
+ Q_D(QmlNumericAnimation);
+ if (!d->to.isNull && t == d->to)
+ return;
+ d->to = t;
+ emit toChanged(t);
+}
+
+/*!
+ \qmlproperty string NumericAnimation::easing
+ \brief the easing curve used for the transition.
+
+ Available values are:
+
+ \list
+ \i \e easeNone - Easing equation function for a simple linear tweening, with no easing.
+ \i \e easeInQuad - Easing equation function for a quadratic (t^2) easing in: accelerating from zero velocity.
+ \i \e easeOutQuad - Easing equation function for a quadratic (t^2) easing out: decelerating to zero velocity.
+ \i \e easeInOutQuad - Easing equation function for a quadratic (t^2) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInQuad - Easing equation function for a quadratic (t^2) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInCubic - Easing equation function for a cubic (t^3) easing in: accelerating from zero velocity.
+ \i \e easeOutCubic - Easing equation function for a cubic (t^3) easing out: decelerating from zero velocity.
+ \i \e easeInOutCubic - Easing equation function for a cubic (t^3) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInCubic - Easing equation function for a cubic (t^3) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInQuart - Easing equation function for a quartic (t^4) easing in: accelerating from zero velocity.
+ \i \e easeOutQuart - Easing equation function for a quartic (t^4) easing out: decelerating from zero velocity.
+ \i \e easeInOutQuart - Easing equation function for a quartic (t^4) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInQuart - Easing equation function for a quartic (t^4) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInQuint - Easing equation function for a quintic (t^5) easing in: accelerating from zero velocity.
+ \i \e easeOutQuint - Easing equation function for a quintic (t^5) easing out: decelerating from zero velocity.
+ \i \e easeInOutQuint - Easing equation function for a quintic (t^5) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInQuint - Easing equation function for a quintic (t^5) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInSine - Easing equation function for a sinusoidal (sin(t)) easing in: accelerating from zero velocity.
+ \i \e easeOutSine - Easing equation function for a sinusoidal (sin(t)) easing out: decelerating from zero velocity.
+ \i \e easeInOutSine - Easing equation function for a sinusoidal (sin(t)) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInSine - Easing equation function for a sinusoidal (sin(t)) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInExpo - Easing equation function for an exponential (2^t) easing in: accelerating from zero velocity.
+ \i \e easeOutExpo - Easing equation function for an exponential (2^t) easing out: decelerating from zero velocity.
+ \i \e easeInOutExpo - Easing equation function for an exponential (2^t) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInExpo - Easing equation function for an exponential (2^t) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInCirc - Easing equation function for a circular (sqrt(1-t^2)) easing in: accelerating from zero velocity.
+ \i \e easeOutCirc - Easing equation function for a circular (sqrt(1-t^2)) easing out: decelerating from zero velocity.
+ \i \e easeInOutCirc - Easing equation function for a circular (sqrt(1-t^2)) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInCirc - Easing equation function for a circular (sqrt(1-t^2)) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInElastic - Easing equation function for an elastic (exponentially decaying sine wave) easing in: accelerating from zero velocity. The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
+ \i \e easeOutElastic - Easing equation function for an elastic (exponentially decaying sine wave) easing out: decelerating from zero velocity. The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
+ \i \e easeInOutElastic - Easing equation function for an elastic (exponentially decaying sine wave) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInElastic - Easing equation function for an elastic (exponentially decaying sine wave) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInBack - Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
+ \i \e easeOutBack - Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out: decelerating from zero velocity.
+ \i \e easeInOutBack - Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInBack - Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeOutBounce - Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out: decelerating from zero velocity.
+ \i \e easeInBounce - Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in: accelerating from zero velocity.
+ \i \e easeInOutBounce - Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInBounce - Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out/in: deceleration until halfway, then acceleration.
+ \endlist
+*/
+
+/*!
+ \property QmlNumericAnimation::easing
+ This property holds the easing curve to use.
+
+ \sa QEasingCurve
+*/
+QString QmlNumericAnimation::easing() const
+{
+ Q_D(const QmlNumericAnimation);
+ return d->easing;
+}
+
+void QmlNumericAnimation::setEasing(const QString &e)
+{
+ Q_D(QmlNumericAnimation);
+ if (d->easing == e)
+ return;
+
+ d->easing = e;
+ d->na->setEasingCurve(stringToCurve(d->easing));
+ emit easingChanged(e);
+}
+
+/*!
+ \qmlproperty string NumericAnimation::properties
+ This property holds the properties this animation should be applied to.
+
+ This is a comma-separated list of properties that should use
+ this animation when they change.
+*/
+/*!
+ \property QmlNumericAnimation::properties
+ \brief the properties this animation should be applied to.
+
+ properties holds a comma-separated list of properties that should use
+ this animation when they change.
+*/
+QString QmlNumericAnimation::properties() const
+{
+ Q_D(const QmlNumericAnimation);
+ return d->properties;
+}
+
+void QmlNumericAnimation::setProperties(const QString &prop)
+{
+ Q_D(QmlNumericAnimation);
+ if (d->properties == prop)
+ return;
+
+ d->properties = prop;
+ emit propertiesChanged(prop);
+}
+
+/*!
+ \qmlproperty list<Item> NumericAnimation::filter
+ This property holds the items selected to be affected by this animation (all if not set).
+ \sa exclude
+*/
+QList<QObject *> *QmlNumericAnimation::filter()
+{
+ Q_D(QmlNumericAnimation);
+ return &d->filter;
+}
+
+/*!
+ \qmlproperty list<Item> NumericAnimation::exclude
+ This property holds the items not to be affected by this animation.
+ \sa filter
+*/
+QList<QObject *> *QmlNumericAnimation::exclude()
+{
+ Q_D(QmlNumericAnimation);
+ return &d->exclude;
+}
+
+void QmlNumericAnimationPrivate::valueChanged(qreal r)
+{
+ if (!fromSourced) {
+ if (from.isNull) {
+ fromValue = qvariant_cast<qreal>(property.read());
+ } else {
+ fromValue = from;
+ }
+ fromSourced = true;
+ }
+
+ if (r == 1.) {
+ property.write(to.value);
+ } else {
+ qreal val = fromValue + (to-fromValue) * r;
+ property.write(val);
+ }
+}
+
+void QmlNumericAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlNumericAnimation);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+ d->fromSourced = false;
+ d->value.QmlTimeLineValue::setValue(0.);
+ d->na->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped);
+ d->na->setFromSourcedValue(&d->fromSourced);
+}
+
+QAbstractAnimation *QmlNumericAnimation::qtAnimation()
+{
+ Q_D(QmlNumericAnimation);
+ return d->na;
+}
+
+void QmlNumericAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlNumericAnimation);
+ Q_UNUSED(direction);
+
+ struct NTransitionData : public QmlTimeLineValue
+ {
+ QmlStateActions actions;
+ void setValue(qreal v)
+ {
+ QmlTimeLineValue::setValue(v);
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QmlBehaviour::_ignore = true;
+ if (v == 1.)
+ action.property.write(action.toValue.toDouble());
+ else {
+ if (action.fromValue.isNull()) {
+ action.fromValue = action.property.read();
+ if (action.fromValue.isNull()) {
+ action.fromValue = QVariant(0.);
+ }
+ }
+ qreal start = action.fromValue.toDouble();
+ qreal end = action.toValue.toDouble();
+ qreal val = start + (end-start) * v;
+ action.property.write(val);
+ }
+ QmlBehaviour::_ignore = false;
+ }
+ }
+ };
+
+ QStringList props = d->properties.split(QLatin1Char(','));
+ for (int ii = 0; ii < props.count(); ++ii)
+ props[ii] = props.at(ii).trimmed();
+ if (!d->propertyName.isEmpty() && !props.contains(d->propertyName))
+ props.append(d->propertyName);
+
+ NTransitionData *data = new NTransitionData;
+
+ QSet<QObject *> objs;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+
+ if ((d->filter.isEmpty() || d->filter.contains(obj)) &&
+ (!d->exclude.contains(obj)) && props.contains(propertyName) &&
+ (!target() || target() == obj)) {
+ objs.insert(obj);
+ Action myAction = action;
+ if (d->from.isValid()) {
+ myAction.fromValue = QVariant(d->from);
+ } else {
+ myAction.fromValue = QVariant();
+ }
+ if (d->to.isValid())
+ myAction.toValue = QVariant(d->to);
+
+ modified << action.property;
+
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+
+ if (d->to.isValid() && target() && !objs.contains(target())) {
+ QObject *obj = target();
+ for (int jj = 0; jj < props.count(); ++jj) {
+ Action myAction;
+ myAction.property = QmlMetaProperty(obj, props.at(jj));
+
+ if (d->from.isValid())
+ myAction.fromValue = QVariant(d->from);
+
+ myAction.toValue = QVariant(d->to);
+ myAction.bv = 0;
+ myAction.event = 0;
+ data->actions << myAction;
+ }
+ }
+
+ if (data->actions.count()) {
+ d->na->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ delete data;
+ }
+}
+
+QML_DEFINE_TYPE(QmlNumericAnimation,NumericAnimation);
+
+QmlAnimationGroup::QmlAnimationGroup(QObject *parent)
+: QmlAbstractAnimation(*(new QmlAnimationGroupPrivate), parent)
+{
+}
+
+QmlAnimationGroup::~QmlAnimationGroup()
+{
+}
+
+QmlList<QmlAbstractAnimation *> *QmlAnimationGroup::animations()
+{
+ Q_D(QmlAnimationGroup);
+ return &d->animations;
+}
+
+/*!
+ \qmlclass SequentialAnimation QmlSequentialAnimation
+ \inherits Animation
+ \brief The SequentialAnimation allows you to run animations sequentially.
+
+ Animations controlled in SequentialAnimation will be run one after the other.
+
+ The following example chains two numeric animations together. The \c MyItem
+ object will animate from its current x position to 100, and then back to 0.
+
+ \code
+ SequentialAnimation {
+ NumericAnimation { target: MyItem; property: "x"; to: 100 }
+ NumericAnimation { target: MyItem; property: "x"; to: 0 }
+ }
+ \endcode
+
+ \sa ParallelAnimation
+*/
+
+QmlSequentialAnimation::QmlSequentialAnimation(QObject *parent) :
+ QmlAnimationGroup(parent)
+{
+ Q_D(QmlAnimationGroup);
+ d->ag = new QSequentialAnimationGroup(this);
+}
+
+QmlSequentialAnimation::~QmlSequentialAnimation()
+{
+}
+
+void QmlSequentialAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlAnimationGroup);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ for (int i = 0; i < d->animations.size(); ++i)
+ d->animations.at(i)->prepare(d->property);
+}
+
+QAbstractAnimation *QmlSequentialAnimation::qtAnimation()
+{
+ Q_D(QmlAnimationGroup);
+ return d->ag;
+}
+
+void QmlSequentialAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlAnimationGroup);
+
+ int inc = 1;
+ int from = 0;
+ if (direction == Backward) {
+ inc = -1;
+ from = d->animations.count() - 1;
+ }
+
+ //XXX removing and readding isn't ideal; we do it to get around the problem mentioned below.
+ for (int i = d->ag->animationCount()-1; i >= 0; --i)
+ d->ag->takeAnimationAt(i);
+
+ for (int ii = from; ii < d->animations.count() && ii >= 0; ii += inc) {
+ d->animations.at(ii)->transition(actions, modified, direction);
+ d->ag->addAnimation(d->animations.at(ii)->qtAnimation());
+ }
+
+ //XXX changing direction means all the animations play in reverse, while we only want the ordering reversed.
+ //d->ag->setDirection(direction == Backward ? QAbstractAnimation::Backward : QAbstractAnimation::Forward);
+}
+
+QML_DEFINE_TYPE(QmlSequentialAnimation,SequentialAnimation);
+
+/*!
+ \qmlclass ParallelAnimation QmlParallelAnimation
+ \inherits Animation
+ \brief The ParallelAnimation allows you to run animations in parallel.
+
+ Animations contained in ParallelAnimation will be run at the same time.
+
+ The following animation demonstrates animating the \c MyItem item
+ to (100,100) by animating the x and y properties in parallel.
+
+ \code
+ ParallelAnimation {
+ NumericAnimation { target: MyItem; property: "x"; to: 100 }
+ NumericAnimation { target: MyItem; property: "y"; to: 100 }
+ }
+ \endcode
+
+ \sa SequentialAnimation
+*/
+/*!
+ \internal
+ \class QmlParallelAnimation
+ \ingroup group_animation
+ \ingroup group_states
+ \brief The QmlParallelAnimation class allows you to run animations in parallel.
+
+ Animations controlled by QmlParallelAnimation will be run at the same time.
+
+ \sa QmlSequentialAnimation
+
+ A QmlParallelAnimation object can be instantiated in Qml using the tag
+ \l{xmlParallelAnimation} {&lt;ParallelAnimation&gt;}.
+*/
+
+QmlParallelAnimation::QmlParallelAnimation(QObject *parent) :
+ QmlAnimationGroup(parent)
+{
+ Q_D(QmlAnimationGroup);
+ d->ag = new QParallelAnimationGroup(this);
+}
+
+QmlParallelAnimation::~QmlParallelAnimation()
+{
+}
+
+void QmlParallelAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlAnimationGroup);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ for (int i = 0; i < d->animations.size(); ++i)
+ d->animations.at(i)->prepare(d->property);
+}
+
+QAbstractAnimation *QmlParallelAnimation::qtAnimation()
+{
+ Q_D(QmlAnimationGroup);
+ return d->ag;
+}
+
+void QmlParallelAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlAnimationGroup);
+
+ for (int ii = 0; ii < d->animations.count(); ++ii) {
+ d->animations.at(ii)->transition(actions, modified, direction);
+ }
+}
+
+QML_DEFINE_TYPE(QmlParallelAnimation,ParallelAnimation);
+
+QVariant QmlVariantAnimationPrivate::interpolateVariant(const QVariant &from, const QVariant &to, qreal progress)
+{
+ if (from.userType() != to.userType())
+ return QVariant();
+
+ QVariantAnimation::Interpolator interpolator = QVariantAnimationPrivate::getInterpolator(from.userType());
+ return interpolator(from.constData(), to.constData(), progress);
+}
+
+//convert a variant from string type to another animatable type
+void QmlVariantAnimationPrivate::convertVariant(QVariant &variant, QVariant::Type type)
+{
+ if (variant.type() != QVariant::String) {
+ variant.convert(type);
+ return;
+ }
+
+ switch (type) {
+ case QVariant::Rect: {
+ variant.setValue(QmlStringConverters::rectFFromString(variant.toString()).toRect());
+ break;
+ }
+ case QVariant::RectF: {
+ variant.setValue(QmlStringConverters::rectFFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Point: {
+ variant.setValue(QmlStringConverters::pointFFromString(variant.toString()).toPoint());
+ break;
+ }
+ case QVariant::PointF: {
+ variant.setValue(QmlStringConverters::pointFFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Size: {
+ variant.setValue(QmlStringConverters::sizeFFromString(variant.toString()).toSize());
+ break;
+ }
+ case QVariant::SizeF: {
+ variant.setValue(QmlStringConverters::sizeFFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Color: {
+ variant.setValue(QmlStringConverters::colorFromString(variant.toString()));
+ break;
+ }
+ default:
+ variant.convert(type);
+ break;
+ }
+}
+
+/*!
+ \qmlclass VariantAnimation QmlVariantAnimation
+ \inherits Animation
+ \brief The VariantAnimation allows you to animate changes in properties of type QVariant.
+
+ Animate a size property over 200ms, from its current size to 20-by-20:
+ \code
+ VariantAnimation { property: "size"; to: "20x20"; duration: 200 }
+ \endcode
+*/
+
+QmlVariantAnimation::QmlVariantAnimation(QObject *parent)
+: QmlAbstractAnimation(*(new QmlVariantAnimationPrivate), parent)
+{
+ Q_D(QmlVariantAnimation);
+ d->init();
+}
+
+QmlVariantAnimation::~QmlVariantAnimation()
+{
+}
+
+void QmlVariantAnimationPrivate::init()
+{
+ Q_Q(QmlVariantAnimation);
+ va = new QmlTimeLineValueAnimator(q);
+ va->setStartValue(QVariant(0.0f));
+ va->setEndValue(QVariant(1.0f));
+}
+
+/*!
+ \qmlproperty int VariantAnimation::duration
+ This property holds the duration of the transition, in milliseconds.
+
+ The default value is 250.
+*/
+/*!
+ \property QmlVariantAnimation::duration
+ \brief the duration of the transition, in milliseconds.
+
+ The default value is 250.
+*/
+int QmlVariantAnimation::duration() const
+{
+ Q_D(const QmlVariantAnimation);
+ return d->va->duration();
+}
+
+void QmlVariantAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qWarning("QmlVariantAnimation: Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QmlVariantAnimation);
+ if (d->va->duration() == duration)
+ return;
+ d->va->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+/*!
+ \qmlproperty real VariantAnimation::from
+ This property holds the starting value.
+ If not set, then the value defined in the start state of the transition.
+*/
+/*!
+ \property QmlVariantAnimation::from
+ \brief the starting value.
+*/
+QVariant QmlVariantAnimation::from() const
+{
+ Q_D(const QmlVariantAnimation);
+ return d->from;
+}
+
+void QmlVariantAnimation::setFrom(const QVariant &f)
+{
+ Q_D(QmlVariantAnimation);
+ if (d->fromIsDefined && f == d->from)
+ return;
+ d->from = f;
+ d->fromIsDefined = f.isValid();
+ emit fromChanged(f);
+}
+
+/*!
+ \qmlproperty real VariantAnimation::to
+ This property holds the ending value.
+ If not set, then the value defined in the end state of the transition.
+*/
+/*!
+ \property QmlVariantAnimation::to
+ \brief the ending value.
+*/
+QVariant QmlVariantAnimation::to() const
+{
+ Q_D(const QmlVariantAnimation);
+ return d->to;
+}
+
+void QmlVariantAnimation::setTo(const QVariant &t)
+{
+ Q_D(QmlVariantAnimation);
+ if (d->toIsDefined && t == d->to)
+ return;
+ d->to = t;
+ d->toIsDefined = t.isValid();
+ emit toChanged(t);
+}
+
+/*!
+ \qmlproperty string VariantAnimation::easing
+ This property holds the easing curve used for the transition.
+
+ See NumericAnimation::easing for a full discussion of easing,
+ and a list of available curves.
+*/
+
+/*!
+ \property QmlVariantAnimation::easing
+ \brief the easing curve to use.
+
+ \sa QEasingCurve
+*/
+QString QmlVariantAnimation::easing() const
+{
+ Q_D(const QmlVariantAnimation);
+ return d->easing;
+}
+
+void QmlVariantAnimation::setEasing(const QString &e)
+{
+ Q_D(QmlVariantAnimation);
+ if (d->easing == e)
+ return;
+
+ d->easing = e;
+ d->va->setEasingCurve(stringToCurve(d->easing));
+ emit easingChanged(e);
+}
+
+/*!
+ \qmlproperty string VariantAnimation::properties
+ This property holds the properties this animation should be applied to.
+
+ This is a comma-separated list of properties that should use
+ this animation when they change.
+*/
+/*!
+ \property QmlVariantAnimation::properties
+ \brief the properties this animation should be applied to
+
+ properties holds a copy separated list of properties that should use
+ this animation when they change.
+*/
+QString QmlVariantAnimation::properties() const
+{
+ Q_D(const QmlVariantAnimation);
+ return d->properties;
+}
+
+void QmlVariantAnimation::setProperties(const QString &prop)
+{
+ Q_D(QmlVariantAnimation);
+ if (d->properties == prop)
+ return;
+
+ d->properties = prop;
+ emit propertiesChanged(prop);
+}
+
+/*!
+ \qmlproperty list<Item> VariantAnimation::filter
+ This property holds the items selected to be affected by this animation (all if not set).
+ \sa exclude
+*/
+QList<QObject *> *QmlVariantAnimation::filter()
+{
+ Q_D(QmlVariantAnimation);
+ return &d->filter;
+}
+
+/*!
+ \qmlproperty list<Item> VariantAnimation::exclude
+ This property holds the items not to be affected by this animation.
+ \sa filter
+*/
+QList<QObject *> *QmlVariantAnimation::exclude()
+{
+ Q_D(QmlVariantAnimation);
+ return &d->exclude;
+}
+
+void QmlVariantAnimationPrivate::valueChanged(qreal r)
+{
+ if (!fromSourced) {
+ if (!fromIsDefined) {
+ from = property.read();
+ }
+ fromSourced = true;
+ }
+
+ if (r == 1.) {
+ property.write(to);
+ } else {
+ QVariant val = interpolateVariant(from, to, r);
+ property.write(val);
+ }
+}
+
+QAbstractAnimation *QmlVariantAnimation::qtAnimation()
+{
+ Q_D(QmlVariantAnimation);
+ return d->va;
+}
+
+void QmlVariantAnimation::prepare(QmlMetaProperty &p)
+{
+ Q_D(QmlVariantAnimation);
+ if (d->userProperty.isNull)
+ d->property = p;
+ else
+ d->property = d->userProperty;
+
+ d->convertVariant(d->to, (QVariant::Type)d->property.propertyType());
+ if (d->fromIsDefined)
+ d->convertVariant(d->from, (QVariant::Type)d->property.propertyType());
+
+ d->fromSourced = false;
+ d->value.QmlTimeLineValue::setValue(0.);
+ d->va->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped);
+ d->va->setFromSourcedValue(&d->fromSourced);
+}
+
+void QmlVariantAnimation::transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QmlVariantAnimation);
+ Q_UNUSED(direction);
+
+ struct NTransitionData : public QmlTimeLineValue
+ {
+ QmlStateActions actions;
+ void setValue(qreal v)
+ {
+ QmlTimeLineValue::setValue(v);
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ if (v == 1.)
+ action.property.write(action.toValue);
+ else {
+ if (action.fromValue.isNull()) {
+ action.fromValue = action.property.read();
+ /*if (action.fromValue.isNull())
+ action.fromValue = QVariant(0.);*/ //XXX can we give a default value for any type?
+ }
+ QVariant val = QmlVariantAnimationPrivate::interpolateVariant(action.fromValue, action.toValue, v);
+ action.property.write(val);
+ }
+ }
+ }
+ };
+
+ QStringList props = d->properties.split(QLatin1Char(','));
+ for (int ii = 0; ii < props.count(); ++ii)
+ props[ii] = props.at(ii).trimmed();
+ if (!d->propertyName.isEmpty() && !props.contains(d->propertyName))
+ props.append(d->propertyName);
+
+ NTransitionData *data = new NTransitionData;
+
+ QSet<QObject *> objs;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ Action &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+
+ if ((d->filter.isEmpty() || d->filter.contains(obj)) &&
+ (!d->exclude.contains(obj)) && props.contains(propertyName) &&
+ (!target() || target() == obj)) {
+ objs.insert(obj);
+ Action myAction = action;
+
+ if (d->fromIsDefined) {
+ myAction.fromValue = d->from;
+ } else {
+ myAction.fromValue = QVariant();
+ }
+ if (d->toIsDefined)
+ myAction.toValue = d->to;
+
+ d->convertVariant(myAction.fromValue, (QVariant::Type)myAction.property.propertyType());
+ d->convertVariant(myAction.toValue, (QVariant::Type)myAction.property.propertyType());
+
+ modified << action.property;
+
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+
+ if (d->toIsDefined && target() && !objs.contains(target())) {
+ QObject *obj = target();
+ for (int jj = 0; jj < props.count(); ++jj) {
+ Action myAction;
+ myAction.property = QmlMetaProperty(obj, props.at(jj));
+
+ if (d->fromIsDefined) {
+ d->convertVariant(d->from, (QVariant::Type)myAction.property.propertyType());
+ myAction.fromValue = d->from;
+ }
+
+ d->convertVariant(d->to, (QVariant::Type)myAction.property.propertyType());
+ myAction.toValue = d->to;
+ myAction.bv = 0;
+ myAction.event = 0;
+ data->actions << myAction;
+ }
+ }
+
+ if (data->actions.count()) {
+ d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ delete data;
+ }
+}
+
+//XXX whats the best name for this? (just Animation?)
+QML_DEFINE_TYPE(QmlVariantAnimation,VariantAnimation);
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlanimation.h b/src/declarative/util/qmlanimation.h
new file mode 100644
index 0000000..578631c
--- /dev/null
+++ b/src/declarative/util/qmlanimation.h
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLANIMATION_H
+#define QMLANIMATION_H
+
+#include <QtCore/qvariant.h>
+#include <QtGui/qcolor.h>
+#include <qmltransition.h>
+#include <qmlpropertyvaluesource.h>
+#include <qmlstate.h>
+#include <qml.h>
+#include <QAbstractAnimation>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlAbstractAnimationPrivate;
+class QmlAnimationGroup;
+class QmlAbstractAnimation : public QmlPropertyValueSource, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAbstractAnimation)
+
+ Q_INTERFACES(QmlParserStatus);
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged);
+ Q_PROPERTY(bool finishPlaying READ finishPlaying WRITE setFinishPlaying NOTIFY finishPlayingChanged());
+ Q_PROPERTY(bool repeat READ repeat WRITE setRepeat NOTIFY repeatChanged);
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged);
+ Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY targetChanged);
+ Q_CLASSINFO("DefaultMethod", "start()");
+ Q_INTERFACES(QmlParserStatus)
+
+public:
+ QmlAbstractAnimation(QObject *parent=0);
+ virtual ~QmlAbstractAnimation();
+
+ bool isRunning() const;
+ void setRunning(bool);
+ bool finishPlaying() const;
+ void setFinishPlaying(bool);
+ bool repeat() const;
+ void setRepeat(bool);
+
+ QmlAnimationGroup *group() const;
+ void setGroup(QmlAnimationGroup *);
+
+ QObject *target() const;
+ void setTarget(QObject *);
+ QString property() const;
+ void setProperty(const QString &);
+
+ void classBegin();
+ void componentComplete();
+
+Q_SIGNALS:
+ void started();
+ void completed();
+ void runningChanged(bool);
+ void repeatChanged(bool);
+ void targetChanged(QObject *, const QString &);
+ void finishPlayingChanged(bool);
+
+public Q_SLOTS:
+ void restart();
+ void start();
+ void stop();
+ void complete();
+
+protected:
+ virtual void setTarget(const QmlMetaProperty &);
+ QmlAbstractAnimation(QmlAbstractAnimationPrivate &dd, QObject *parent);
+
+public:
+ enum TransitionDirection { Forward, Backward };
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual void prepare(QmlMetaProperty &);
+ virtual QAbstractAnimation *qtAnimation() = 0;
+
+private Q_SLOTS:
+ void timelineComplete();
+};
+
+QML_DECLARE_TYPE(QmlAbstractAnimation);
+
+class QmlPauseAnimationPrivate;
+class QmlPauseAnimation : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlPauseAnimation);
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged);
+
+public:
+ QmlPauseAnimation(QObject *parent=0);
+ virtual ~QmlPauseAnimation();
+
+ int duration() const;
+ void setDuration(int);
+
+Q_SIGNALS:
+ void durationChanged(int);
+
+protected:
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+QML_DECLARE_TYPE(QmlPauseAnimation);
+
+class QmlColorAnimationPrivate;
+class QmlColorAnimation : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlColorAnimation);
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged);
+ Q_PROPERTY(QColor from READ from WRITE setFrom NOTIFY fromChanged);
+ Q_PROPERTY(QColor to READ to WRITE setTo NOTIFY toChanged);
+ Q_PROPERTY(QString easing READ easing WRITE setEasing NOTIFY easingChanged);
+ Q_PROPERTY(QList<QObject *>* filter READ filter);
+ Q_PROPERTY(QList<QObject *>* exclude READ exclude);
+
+public:
+ QmlColorAnimation(QObject *parent=0);
+ virtual ~QmlColorAnimation();
+
+ int duration() const;
+ void setDuration(int);
+
+ QColor from() const;
+ void setFrom(const QColor &);
+
+ QColor to() const;
+ void setTo(const QColor &);
+
+ QString easing() const;
+ void setEasing(const QString &);
+
+ QList<QObject *> *filter();
+
+ QList<QObject *> *exclude();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void fromChanged(const QColor &);
+ void toChanged(const QColor &);
+ void easingChanged(const QString &);
+};
+QML_DECLARE_TYPE(QmlColorAnimation);
+
+class QmlRunScriptActionPrivate;
+class QmlRunScriptAction : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlRunScriptAction);
+
+ Q_PROPERTY(QString script READ script WRITE setScript NOTIFY scriptChanged);
+ Q_PROPERTY(QString file READ file WRITE setFile NOTIFY fileChanged);
+
+public:
+ QmlRunScriptAction(QObject *parent=0);
+ virtual ~QmlRunScriptAction();
+
+ QString script() const;
+ void setScript(const QString &);
+
+ QString file() const;
+ void setFile(const QString &);
+
+Q_SIGNALS:
+ void fileChanged(const QString &);
+ void scriptChanged(const QString &);
+
+protected:
+ virtual QAbstractAnimation *qtAnimation();
+};
+QML_DECLARE_TYPE(QmlRunScriptAction);
+
+class QmlSetPropertyActionPrivate;
+class QmlSetPropertyAction : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlSetPropertyAction);
+
+ Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged);
+ Q_PROPERTY(QList<QObject *>* filter READ filter);
+ Q_PROPERTY(QList<QObject *>* exclude READ exclude);
+ Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged);
+
+public:
+ QmlSetPropertyAction(QObject *parent=0);
+ virtual ~QmlSetPropertyAction();
+
+ QString properties() const;
+ void setProperties(const QString &);
+
+ QList<QObject *> *filter();
+ QList<QObject *> *exclude();
+
+ QVariant value() const;
+ void setValue(const QVariant &);
+
+Q_SIGNALS:
+ void valueChanged(const QVariant &);
+ void propertiesChanged(const QString &);
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+QML_DECLARE_TYPE(QmlSetPropertyAction);
+
+class QmlParentChangeActionPrivate;
+class QmlParentChangeAction : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlParentChangeAction);
+
+ //XXX should have parent property as well for when it isn't part of a transition
+
+public:
+ QmlParentChangeAction(QObject *parent=0);
+ virtual ~QmlParentChangeAction();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+QML_DECLARE_TYPE(QmlParentChangeAction);
+
+class QmlNumericAnimationPrivate;
+class QmlNumericAnimation : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlNumericAnimation);
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged);
+ Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged);
+ Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged);
+ Q_PROPERTY(QString easing READ easing WRITE setEasing NOTIFY easingChanged);
+ Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged);
+ Q_PROPERTY(QList<QObject *>* filter READ filter);
+ Q_PROPERTY(QList<QObject *>* exclude READ exclude);
+
+public:
+ QmlNumericAnimation(QObject *parent=0);
+ virtual ~QmlNumericAnimation();
+
+ int duration() const;
+ void setDuration(int);
+
+ qreal from() const;
+ void setFrom(qreal);
+
+ qreal to() const;
+ void setTo(qreal);
+
+ QString easing() const;
+ void setEasing(const QString &);
+
+ QString properties() const;
+ void setProperties(const QString &);
+
+ QList<QObject *> *filter();
+ QList<QObject *> *exclude();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void fromChanged(qreal);
+ void toChanged(qreal);
+ void easingChanged(const QString &);
+ void propertiesChanged(const QString &);
+};
+QML_DECLARE_TYPE(QmlNumericAnimation);
+
+#if 0
+class QmlDiscreteAnimation : public QmlAbstractAnimation
+{
+Q_OBJECT
+};
+#endif
+
+class QmlAnimationGroupPrivate;
+class QmlAnimationGroup : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAnimationGroup);
+
+ Q_CLASSINFO("DefaultProperty", "animations");
+ Q_PROPERTY(QmlList<QmlAbstractAnimation *> *animations READ animations);
+
+public:
+ QmlAnimationGroup(QObject *parent);
+ virtual ~QmlAnimationGroup();
+
+ QmlList<QmlAbstractAnimation *>* animations();
+};
+
+class QmlSequentialAnimation : public QmlAnimationGroup
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAnimationGroup);
+
+public:
+ QmlSequentialAnimation(QObject *parent=0);
+ virtual ~QmlSequentialAnimation();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+QML_DECLARE_TYPE(QmlSequentialAnimation);
+
+class QmlParallelAnimation : public QmlAnimationGroup
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlAnimationGroup);
+
+public:
+ QmlParallelAnimation(QObject *parent=0);
+ virtual ~QmlParallelAnimation();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+};
+QML_DECLARE_TYPE(QmlParallelAnimation);
+
+class QmlVariantAnimationPrivate;
+class QmlVariantAnimation : public QmlAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlVariantAnimation);
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged);
+ Q_PROPERTY(QVariant from READ from WRITE setFrom NOTIFY fromChanged);
+ Q_PROPERTY(QVariant to READ to WRITE setTo NOTIFY toChanged);
+ Q_PROPERTY(QString easing READ easing WRITE setEasing NOTIFY easingChanged);
+ Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged);
+ Q_PROPERTY(QList<QObject *>* filter READ filter);
+ Q_PROPERTY(QList<QObject *>* exclude READ exclude);
+
+public:
+ QmlVariantAnimation(QObject *parent=0);
+ virtual ~QmlVariantAnimation();
+
+ int duration() const;
+ void setDuration(int);
+
+ QVariant from() const;
+ void setFrom(const QVariant &);
+
+ QVariant to() const;
+ void setTo(const QVariant &);
+
+ QString easing() const;
+ void setEasing(const QString &);
+
+ QString properties() const;
+ void setProperties(const QString &);
+
+ QList<QObject *> *filter();
+ QList<QObject *> *exclude();
+
+protected:
+ virtual void transition(QmlStateActions &actions,
+ QmlMetaProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+ virtual void prepare(QmlMetaProperty &);
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void fromChanged(QVariant);
+ void toChanged(QVariant);
+ void easingChanged(const QString &);
+ void propertiesChanged(const QString &);
+};
+QML_DECLARE_TYPE(QmlVariantAnimation);
+
+#endif // QMLANIMATION_H
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmlanimation_p.h b/src/declarative/util/qmlanimation_p.h
new file mode 100644
index 0000000..00937a6
--- /dev/null
+++ b/src/declarative/util/qmlanimation_p.h
@@ -0,0 +1,396 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLANIMATION_P_H
+#define QMLANIMATION_P_H
+
+#include <private/qobject_p.h>
+#include <private/qmlnullablevalue_p.h>
+#include <qmlanimation.h>
+#include <qml.h>
+#include <qmlcontext.h>
+#include <private/qvariantanimation_p.h>
+#include <QPauseAnimation>
+#include <QVariantAnimation>
+#include <QAnimationGroup>
+#include <QColor>
+#include <qmltimelinevalueproxy.h>
+
+QT_BEGIN_NAMESPACE
+
+//interface for classes that provide animation actions for QActionAnimation
+class QAbstractAnimationAction
+{
+public:
+ virtual ~QAbstractAnimationAction() {}
+ virtual void doAction() = 0;
+};
+
+//templated animation action
+//allows us to specify an action that calls a function of a class.
+//(so that class doesn't have to inherit QmlAbstractAnimationAction)
+template<class T, void (T::*method)()>
+class QAnimationActionProxy : public QAbstractAnimationAction
+{
+public:
+ QAnimationActionProxy(T *p) : m_p(p) {}
+ virtual void doAction() { (m_p->*method)(); }
+
+private:
+ T *m_p;
+};
+
+//performs an action of type QAbstractAnimationAction
+class QActionAnimation : public QAbstractAnimation
+{
+public:
+ QActionAnimation(QObject *parent = 0) : QAbstractAnimation(parent), animAction(0), policy(KeepWhenStopped) {}
+ QActionAnimation(QAbstractAnimationAction *action, QObject *parent = 0)
+ : QAbstractAnimation(parent), animAction(action), policy(KeepWhenStopped) {}
+ virtual int duration() const { return 0; }
+ void setAnimAction(QAbstractAnimationAction *action, DeletionPolicy p)
+ {
+ if (state() == Running)
+ stop();
+ animAction = action;
+ policy = p;
+ }
+protected:
+ virtual void updateCurrentTime(int) {}
+
+ virtual void updateState(State /*oldState*/, State newState)
+ {
+ if (newState == Running) {
+ if (animAction)
+ animAction->doAction();
+ } else if (newState == Stopped && policy == DeleteWhenStopped) {
+ delete animAction;
+ animAction = 0;
+ }
+ }
+
+private:
+ QAbstractAnimationAction *animAction;
+ DeletionPolicy policy;
+};
+
+//animates QmlTimeLineValue (assumes start and end values will be reals or compatible)
+class QmlTimeLineValueAnimator : public QVariantAnimation
+{
+public:
+ QmlTimeLineValueAnimator(QObject *parent = 0) : QVariantAnimation(parent), animValue(0), fromSourced(0), policy(KeepWhenStopped) {}
+ void setAnimValue(QmlTimeLineValue *value, DeletionPolicy p)
+ {
+ if (state() == Running)
+ stop();
+ animValue = value;
+ policy = p;
+ }
+ void setFromSourcedValue(bool *value)
+ {
+ fromSourced = value;
+ }
+protected:
+ virtual void updateCurrentValue(const QVariant &value)
+ {
+ if (animValue)
+ animValue->setValue(value.toDouble());
+ }
+ virtual void updateState(State oldState, State newState)
+ {
+ QVariantAnimation::updateState(oldState, newState);
+ if (newState == Running) {
+ //check for new from every loop
+ if (fromSourced)
+ *fromSourced = false;
+ } else if (newState == Stopped && policy == DeleteWhenStopped) {
+ delete animValue;
+ animValue = 0;
+ }
+ }
+
+private:
+ QmlTimeLineValue *animValue;
+ bool *fromSourced;
+ DeletionPolicy policy;
+};
+
+//an animation that just gives a tick
+template<class T, void (T::*method)(int)>
+class QTickAnimationProxy : public QAbstractAnimation
+{
+public:
+ QTickAnimationProxy(T *p, QObject *parent = 0) : QAbstractAnimation(parent), m_p(p) {}
+ virtual int duration() const { return -1; }
+protected:
+ virtual void updateCurrentTime(int msec) { (m_p->*method)(msec); }
+
+private:
+ T *m_p;
+};
+
+class QmlAbstractAnimationPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlAbstractAnimation);
+public:
+ QmlAbstractAnimationPrivate()
+ : running(false), finishPlaying(false), repeat(false),
+ connectedTimeLine(false), componentComplete(true), startOnCompletion(false),
+ target(0), group(0) {}
+
+ bool running;
+ bool finishPlaying;
+ bool repeat;
+ bool connectedTimeLine;
+
+ bool componentComplete;
+ bool startOnCompletion;
+
+ void commence();
+
+ QmlNullableValue<QmlMetaProperty> userProperty;
+ QObject *target;
+ QString propertyName;
+
+ QmlMetaProperty property;
+ QmlAnimationGroup *group;
+};
+
+class QmlPauseAnimationPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlPauseAnimation);
+public:
+ QmlPauseAnimationPrivate()
+ : QmlAbstractAnimationPrivate(), pa(0) {}
+
+ void init();
+
+ QPauseAnimation *pa;
+};
+
+class QmlColorAnimationPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlColorAnimation);
+public:
+ QmlColorAnimationPrivate()
+ : QmlAbstractAnimationPrivate(), fromSourced(false), fromIsDefined(false), toIsDefined(false),
+ ca(0), value(this, &QmlColorAnimationPrivate::valueChanged)
+ {
+ if (!colorInterpolator)
+ colorInterpolator = QVariantAnimationPrivate::getInterpolator(QVariant::Color);
+ }
+
+ void init();
+
+ QString easing;
+
+ QColor fromValue;
+ QColor toValue;
+
+ QList<QObject *> filter;
+ QList<QObject *> exclude;
+
+ bool fromSourced;
+ bool fromIsDefined;
+ bool toIsDefined;
+
+ QmlTimeLineValueAnimator *ca;
+ virtual void valueChanged(qreal);
+
+ QmlTimeLineValueProxy<QmlColorAnimationPrivate> value;
+
+ static QVariantAnimation::Interpolator colorInterpolator;
+};
+
+class QmlRunScriptActionPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlRunScriptAction);
+public:
+ QmlRunScriptActionPrivate()
+ : QmlAbstractAnimationPrivate(), proxy(this), rsa(0) {}
+
+ void init();
+
+ QString script;
+ QString file;
+
+ void execute();
+
+ QAnimationActionProxy<QmlRunScriptActionPrivate,
+ &QmlRunScriptActionPrivate::execute> proxy;
+ QActionAnimation *rsa;
+};
+
+class QmlSetPropertyActionPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlSetPropertyAction);
+public:
+ QmlSetPropertyActionPrivate()
+ : QmlAbstractAnimationPrivate(), proxy(this), spa(0) {}
+
+ void init();
+
+ QString properties;
+ QList<QObject *> filter;
+ QList<QObject *> exclude;
+
+ QmlNullableValue<QVariant> value;
+
+ void doAction();
+
+ QAnimationActionProxy<QmlSetPropertyActionPrivate,
+ &QmlSetPropertyActionPrivate::doAction> proxy;
+ QActionAnimation *spa;
+};
+
+class QmlParentChangeActionPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlParentChangeAction);
+public:
+ QmlParentChangeActionPrivate()
+ : QmlAbstractAnimationPrivate() {}
+
+ void init();
+
+ void doAction();
+ QActionAnimation *cpa;
+};
+
+class QmlNumericAnimationPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlNumericAnimation);
+public:
+ QmlNumericAnimationPrivate()
+ : QmlAbstractAnimationPrivate(), fromSourced(false), na(0), value(this, &QmlNumericAnimationPrivate::valueChanged) {}
+
+ void init();
+
+ QmlNullableValue<qreal> from;
+ QmlNullableValue<qreal> to;
+
+ QString easing;
+
+ QString properties;
+ QList<QObject *> filter;
+ QList<QObject *> exclude;
+
+ bool fromSourced;
+ qreal fromValue;
+ QmlTimeLineValueAnimator *na;
+ virtual void valueChanged(qreal);
+
+ QmlTimeLineValueProxy<QmlNumericAnimationPrivate> value;
+};
+
+class QmlAnimationGroupPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlAnimationGroup);
+public:
+ QmlAnimationGroupPrivate()
+ : QmlAbstractAnimationPrivate(), animations(this), ag(0) {}
+
+ struct AnimationList : public QmlConcreteList<QmlAbstractAnimation *>
+ {
+ AnimationList(QmlAnimationGroupPrivate *p)
+ : anim(p) {}
+ virtual void append(QmlAbstractAnimation *a) {
+ QmlConcreteList<QmlAbstractAnimation *>::append(a);
+ a->setGroup(anim->q_func());
+ }
+ virtual void clear()
+ {
+ for (int i = 0; i < count(); ++i)
+ at(i)->setGroup(0);
+ QmlConcreteList<QmlAbstractAnimation *>::clear();
+ }
+ virtual void removeAt(int i)
+ {
+ at(i)->setGroup(0);
+ QmlConcreteList<QmlAbstractAnimation *>::removeAt(i);
+ }
+ virtual void insert(int i, QmlAbstractAnimation *a)
+ {
+ QmlConcreteList<QmlAbstractAnimation *>::insert(i, a);
+ a->setGroup(anim->q_func());
+ }
+
+ QmlAnimationGroupPrivate *anim;
+ };
+
+ AnimationList animations;
+ QAnimationGroup *ag;
+};
+
+class QmlVariantAnimationPrivate : public QmlAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QmlVariantAnimation);
+public:
+ QmlVariantAnimationPrivate()
+ : QmlAbstractAnimationPrivate(), fromSourced(false), fromIsDefined(false), toIsDefined(false),
+ va(0), value(this, &QmlVariantAnimationPrivate::valueChanged) {}
+
+ void init();
+
+ QVariant from;
+ QVariant to;
+
+ QString easing;
+
+ QString properties;
+ QList<QObject *> filter;
+ QList<QObject *> exclude;
+
+ bool fromSourced;
+ bool fromIsDefined;
+ bool toIsDefined;
+
+ QmlTimeLineValueAnimator *va;
+ virtual void valueChanged(qreal);
+
+ QmlTimeLineValueProxy<QmlVariantAnimationPrivate> value;
+
+ static QVariant interpolateVariant(const QVariant &from, const QVariant &to, qreal progress);
+ static void convertVariant(QVariant &variant, QVariant::Type type);
+};
+
+#endif // QMLANIMATION_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlbehaviour.cpp b/src/declarative/util/qmlbehaviour.cpp
new file mode 100644
index 0000000..354c7e3
--- /dev/null
+++ b/src/declarative/util/qmlbehaviour.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qobject_p.h>
+#include "qmlanimation.h"
+#include "qmltransition.h"
+#include "qmlbehaviour.h"
+#include <QtDeclarative/qmlcontext.h>
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QmlBehaviour,Behaviour);
+
+
+class QmlBehaviourData : public QObject
+{
+Q_OBJECT
+public:
+ QmlBehaviourData(QObject *parent)
+ : QObject(parent) {}
+
+ Q_PROPERTY(QVariant endValue READ endValue NOTIFY valuesChanged);
+ Q_PROPERTY(QVariant startValue READ startValue NOTIFY valuesChanged);
+ QVariant endValue() const { return e; }
+ QVariant startValue() const { return s; }
+
+ QVariant e;
+ QVariant s;
+
+Q_SIGNALS:
+ void valuesChanged();
+
+private:
+ friend class QmlBehaviour;
+};
+
+class QmlBehaviourPrivate : public QObjectPrivate
+{
+public:
+ QmlBehaviourPrivate()
+ : context(0), valueData(0), operations(this) {}
+ QmlMetaProperty property;
+ QVariant currentValue;
+
+ QVariant fromValue;
+ QVariant toValue;
+ QmlContext *context;
+ QmlBehaviourData *valueData;
+ class AnimationList : public QmlConcreteList<QmlAbstractAnimation *>
+ {
+ public:
+ AnimationList(QmlBehaviourPrivate *parent) : _parent(parent) {}
+ virtual void append(QmlAbstractAnimation *a)
+ {
+ QmlConcreteList<QmlAbstractAnimation *>::append(a);
+ _parent->group->addAnimation(a->qtAnimation());
+ }
+ virtual void clear() { QmlConcreteList<QmlAbstractAnimation *>::clear(); } //###
+ private:
+ QmlBehaviourPrivate *_parent;
+ };
+ AnimationList operations;
+ QSequentialAnimationGroup *group;
+};
+
+/*!
+ \qmlclass Behaviour QmlBehaviour
+ \brief The Behaviour element allows you to specify a default animation for a property change.
+
+ In example below, the rect will use a bounce easing curve over 200 millisecond for any changes to its y property:
+ \code
+ Rect {
+ width: 20; height: 20
+ color: "#00ff00"
+ y: 200 //initial value
+ y: Behaviour {
+ NumericAnimation {
+ easing: "easeOutBounce(amplitude:100)"
+ duration: 200
+ }
+ }
+ }
+ \endcode
+*/
+
+QmlBehaviour::QmlBehaviour(QObject *parent)
+: QmlPropertyValueSource(*(new QmlBehaviourPrivate), parent)
+{
+ Q_D(QmlBehaviour);
+ d->valueData = new QmlBehaviourData(this);
+ d->group = new QSequentialAnimationGroup(this);
+}
+
+/*!
+ \qmlproperty QVariant Behaviour::fromValue
+ This property holds a selector specifying a starting value for the behaviour
+
+ If you only want the behaviour to apply when the change starts at a
+ specific value you can specify fromValue. This selector is used in conjunction
+ with the toValue selector.
+*/
+
+QVariant QmlBehaviour::fromValue() const
+{
+ Q_D(const QmlBehaviour);
+ return d->fromValue;
+}
+
+void QmlBehaviour::setFromValue(const QVariant &v)
+{
+ Q_D(QmlBehaviour);
+ d->fromValue = v;
+}
+
+/*!
+ \qmlproperty QVariant Behaviour::toValue
+ This property holds a selector specifying a ending value for the behaviour
+
+ If you only want the behaviour to apply when the change ends at a
+ specific value you can specify toValue. This selector is used in conjunction
+ with the fromValue selector.
+*/
+
+QVariant QmlBehaviour::toValue() const
+{
+ Q_D(const QmlBehaviour);
+ return d->toValue;
+}
+
+void QmlBehaviour::setToValue(const QVariant &v)
+{
+ Q_D(QmlBehaviour);
+ d->toValue = v;
+}
+
+QmlList<QmlAbstractAnimation *>* QmlBehaviour::operations()
+{
+ Q_D(QmlBehaviour);
+ return &d->operations;
+}
+
+QmlBehaviour::~QmlBehaviour()
+{
+ //### do we need any other cleanup here?
+}
+
+bool QmlBehaviour::_ignore = false;
+void QmlBehaviour::propertyValueChanged()
+{
+ Q_D(QmlBehaviour);
+ if (_ignore)
+ return;
+
+ QVariant newValue = d->property.read();
+
+ if ((!fromValue().isValid() || fromValue() == d->currentValue) &&
+ (!toValue().isValid() || toValue() == newValue)) {
+
+ //### does this clean up everything needed?
+ d->group->stop();
+
+ d->valueData->e = newValue;
+ d->valueData->s = d->currentValue;
+ emit d->valueData->valuesChanged();
+
+ QmlStateOperation::ActionList actions;
+ Action action;
+ action.property = d->property;
+ action.fromValue = d->currentValue;
+ action.toValue = newValue;
+ actions << action;
+
+ _ignore = true;
+ d->property.write(d->currentValue);
+
+ QList<QmlMetaProperty> after;
+ for (int ii = 0; ii < d->operations.count(); ++ii) {
+ d->operations.at(ii)->transition(actions, after, QmlAbstractAnimation::Forward);
+ }
+ d->group->start();
+ if (!after.contains(d->property))
+ d->property.write(newValue);
+ _ignore = false;
+ }
+
+ d->currentValue = newValue;
+}
+
+void QmlBehaviour::setTarget(const QmlMetaProperty &property)
+{
+ Q_D(QmlBehaviour);
+ d->property = property;
+ d->currentValue = property.read();
+ d->property.connectNotifier(this, SLOT(propertyValueChanged()));
+}
+
+void QmlBehaviour::classBegin()
+{
+ Q_D(QmlBehaviour);
+ if (!d->context) {
+ d->context = new QmlContext(qmlContext(this), this);
+ d->context->addDefaultObject(d->valueData);
+ }
+ d->context->activate();
+}
+
+void QmlBehaviour::classComplete()
+{
+ Q_D(QmlBehaviour);
+ d->context->deactivate();
+}
+
+#include "qmlbehaviour.moc"
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlbehaviour.h b/src/declarative/util/qmlbehaviour.h
new file mode 100644
index 0000000..3d25cd8
--- /dev/null
+++ b/src/declarative/util/qmlbehaviour.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBEHAVIOUR_H
+#define QMLBEHAVIOUR_H
+
+#include <qmlpropertyvaluesource.h>
+#include <qml.h>
+#include <qmlstate.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlAbstractAnimation;
+class QmlBehaviourPrivate;
+class Q_DECLARATIVE_EXPORT QmlBehaviour : public QmlPropertyValueSource,
+ public QmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlBehaviour)
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QVariant from READ fromValue WRITE setFromValue);
+ Q_PROPERTY(QVariant to READ toValue WRITE setToValue);
+ Q_CLASSINFO("DefaultProperty", "operations");
+ Q_PROPERTY(QmlList<QmlAbstractAnimation *>* operations READ operations);
+
+public:
+ QmlBehaviour(QObject *parent=0);
+ ~QmlBehaviour();
+
+ QVariant fromValue() const;
+ void setFromValue(const QVariant &);
+ QVariant toValue() const;
+ void setToValue(const QVariant &);
+ virtual void setTarget(const QmlMetaProperty &);
+
+ QmlList<QmlAbstractAnimation *>* operations();
+
+ static bool _ignore;
+
+protected:
+ virtual void classBegin();
+ virtual void classComplete();
+
+private Q_SLOTS:
+ void propertyValueChanged();
+};
+QML_DECLARE_TYPE(QmlBehaviour);
+
+
+#endif // QMLBEHAVIOUR_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmlbind.cpp b/src/declarative/util/qmlbind.cpp
new file mode 100644
index 0000000..59bfd75
--- /dev/null
+++ b/src/declarative/util/qmlbind.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qmlbindablevalue.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <private/qobject_p.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qdebug.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptcontext.h>
+#include <QtScript/qscriptengine.h>
+#include <private/qmlnullablevalue_p.h>
+#include "qmlbind.h"
+
+QT_BEGIN_NAMESPACE
+class QmlBindPrivate : public QObjectPrivate
+{
+public:
+ QmlBindPrivate() : when(true), obj(0) {}
+
+ bool when;
+ QObject *obj;
+ QString prop;
+ QmlNullableValue<QVariant> value;
+};
+
+QML_DEFINE_TYPE(QmlBind,Bind);
+/*!
+ \qmlclass Bind QmlBind
+ \brief The Bind element allows arbitrary property bindings to be created.
+
+ Sometimes it is necessary to bind to a property of an object that wasn't
+ directly instantiated by QML - generally a property of a class exported
+ to QML by C++. In these cases, regular property binding doesn't work. Bind
+ allows you to bind any value to any property.
+
+ For example, imagine a C++ application that maps an "app.enteredText"
+ property into QML. You could use Bind to update the enteredText property
+ like this.
+ \code
+ TextEdit { id: myTextField; text: "Please type here..." }
+ Bind { target: app; property: "enteredText"; value: myTextField.text />
+ \endcode
+ Whenever the text in the TextEdit is updated, the C++ property will be
+ updated also.
+
+ If the bind target or bind property is changed, the bound value is
+ immediately pushed onto the new target.
+
+ \sa {qmlforcpp}{Qt Declarative Markup Language For C++ Programmers}
+ */
+/*!
+ \internal
+ \class QmlBind
+ \ingroup group_utility
+ \brief The QmlBind class allows arbitrary property bindings to be created.
+
+ Simple bindings are usually earier to do in-place rather than creating a
+ QmlBind item. For that reason, QmlBind is usually used to transfer property information
+ from Qml to C++.
+
+ \sa cppqml
+ */
+QmlBind::QmlBind(QObject *parent)
+ : QObject(*(new QmlBindPrivate), parent)
+{
+}
+
+QmlBind::~QmlBind()
+{
+}
+
+bool QmlBind::when() const
+{
+ Q_D(const QmlBind);
+ return d->when;
+}
+
+void QmlBind::setWhen(bool v)
+{
+ Q_D(QmlBind);
+ d->when = v;
+ eval();
+}
+
+/*!
+ \qmlproperty Object Bind::target
+
+ The object to be updated.
+ */
+/*!
+ \property QmlBind::target
+ \brief the object to be updated.
+*/
+QObject *QmlBind::object()
+{
+ Q_D(const QmlBind);
+ return d->obj;
+}
+
+void QmlBind::setObject(QObject *obj)
+{
+ Q_D(QmlBind);
+ d->obj = obj;
+ eval();
+}
+
+/*!
+ \qmlproperty string Bind::property
+
+ The property to be updated.
+ */
+/*!
+ \property QmlBind::property
+ \brief the property of the target to be updated.
+*/
+QString QmlBind::property() const
+{
+ Q_D(const QmlBind);
+ return d->prop;
+}
+
+void QmlBind::setProperty(const QString &p)
+{
+ Q_D(QmlBind);
+ d->prop = p;
+ eval();
+}
+
+/*!
+ \qmlproperty any Bind::value
+
+ The value to be set on the target object and property. This can be a
+ constant (which isn't very useful), or a bound expression.
+ */
+/*!
+ \property QmlBind::value
+ \brief the value to bind to.
+*/
+QVariant QmlBind::value() const
+{
+ Q_D(const QmlBind);
+ return d->value.value;
+}
+
+void QmlBind::setValue(const QVariant &v)
+{
+ Q_D(QmlBind);
+ d->value.value = v;
+ d->value.isNull = false;
+ eval();
+}
+
+void QmlBind::eval()
+{
+ Q_D(QmlBind);
+ if (!d->obj || d->value.isNull || !d->when)
+ return;
+
+ QmlMetaProperty prop(d->obj, d->prop);
+ prop.write(d->value.value);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlbind.h b/src/declarative/util/qmlbind.h
new file mode 100644
index 0000000..355edfd
--- /dev/null
+++ b/src/declarative/util/qmlbind.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBIND_H
+#define QMLBIND_H
+
+#include <qfxglobal.h>
+#include <QtCore/qobject.h>
+#include "qml.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlBindPrivate;
+class Q_DECLARATIVE_EXPORT QmlBind : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlBind);
+
+ Q_PROPERTY(QObject *target READ object WRITE setObject);
+ Q_PROPERTY(QString property READ property WRITE setProperty);
+ Q_PROPERTY(QVariant value READ value WRITE setValue);
+
+public:
+ QmlBind(QObject *parent=0);
+ ~QmlBind();
+
+ Q_PROPERTY(bool when READ when WRITE setWhen);
+ bool when() const;
+ void setWhen(bool);
+
+ QObject *object();
+ void setObject(QObject *);
+
+ QString property() const;
+ void setProperty(const QString &);
+
+ QVariant value() const;
+ void setValue(const QVariant &);
+
+private:
+ void eval();
+};
+QML_DECLARE_TYPE(QmlBind);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/util/qmlconnection.cpp b/src/declarative/util/qmlconnection.cpp
new file mode 100644
index 0000000..8f6c908
--- /dev/null
+++ b/src/declarative/util/qmlconnection.cpp
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlconnection.h"
+#include <QtDeclarative/qmlexpression.h>
+#include "private/qmlboundsignal_p.h"
+#include "private/qobject_p.h"
+#include <QtDeclarative/qmlcontext.h>
+#include <QtCore/qdebug.h>
+
+
+QT_BEGIN_NAMESPACE
+class QmlConnectionPrivate : public QObjectPrivate
+{
+public:
+ QmlConnectionPrivate() : boundsignal(0), signalSender(0), componentcomplete(false) {}
+
+ QmlBoundSignal *boundsignal;
+ QObject *signalSender;
+ QString script;
+ QString signal;
+ bool componentcomplete;
+};
+
+/*!
+ \qmlclass Connection QmlConnection
+ \brief A Connection object describes generalized connections to signals.
+
+ JavaScript-in-HTML style signal properties do not allow:
+ \list
+ \i connecting to signals with the same name but different parameters
+ \i conformance checking that parameters are correctly named
+ \i multiple connections to the same signal
+ \i connections outside the scope of the signal sender
+ \i signals in classes with coincidentally-named on<Signal> properties
+ \endlist
+
+ When any of these is needed, the Connection object can be used instead.
+ Where a signal could be connected like this:
+
+ \qml
+MouseRegion {
+ onClicked: { foo(x+123,y+456) }
+}
+ \endqml
+
+ An equivalent binding can be made with a Connection object:
+
+ \qml
+MouseRegion {
+ Connection {
+ signal: "clicked(x,y)"
+ script: { foo(x+123,y+456) }
+ }
+}
+ \endqml
+
+ More generally, the Connection object can be a child of some other object than
+ the sender of the signal, and the script is the default attribute:
+
+ \qml
+MouseRegion {
+ id: mr
+}
+...
+Connection {
+ sender: mr
+ signal: "clicked(x,y)"
+ script: { foo(x+123,y+456) }
+}
+ \endqml
+*/
+
+/*!
+ \internal
+ \class QmlConnection
+ \brief The QmlConnection class describes generalized connections to signals.
+
+ QmlSetProperties is a mechanism for connecting a script to be run when
+ some object sends a signal.
+*/
+QmlConnection::QmlConnection(QObject *parent) :
+ QObject(*(new QmlConnectionPrivate), parent)
+{
+}
+
+QmlConnection::~QmlConnection()
+{
+ Q_D(QmlConnection);
+ delete d->boundsignal;
+}
+
+/*!
+ \qmlproperty Object Connection::sender
+ This property holds the object that sends the signal.
+
+ By default, the sender is assumed to be the parent of the Connection.
+*/
+
+/*!
+ \property QmlConnection::sender
+ \brief the object that sends the signal.
+
+ By default, the sender is assumed to be the parent of the Connection.
+
+ Note that the set/get methods are setSignalSender() and signalSender(),
+ due to the pre-existence of QObject::sender().
+*/
+QObject *QmlConnection::signalSender() const
+{
+ Q_D(const QmlConnection);
+ return d->signalSender ? d->signalSender : parent();
+}
+
+void QmlConnection::setSignalSender(QObject *obj)
+{
+ Q_D(QmlConnection);
+ if (d->signalSender == obj)
+ return;
+ disconnectIfValid();
+ d->signalSender = obj;
+ connectIfValid();
+}
+
+void QmlConnection::connectIfValid()
+{
+ Q_D(QmlConnection);
+ if (!d->componentcomplete)
+ return;
+ // boundsignal must not exist
+ if ((d->signalSender || parent()) && !d->signal.isEmpty() && !d->script.isEmpty()) {
+ // create
+ // XXX scope?
+ int sigIdx = -1;
+ int lparen = d->signal.indexOf(QLatin1Char('('));
+ QList<QByteArray> sigparams;
+ if (lparen >= 0 && d->signal.length() > lparen+2) {
+ QStringList l = d->signal.mid(lparen+1,d->signal.length()-lparen-2).split(QLatin1Char(','));
+ foreach (const QString &s, l) {
+ sigparams.append(s.toLatin1());
+ }
+ }
+ QString signalname = d->signal.left(lparen);
+ QObject *sender = d->signalSender ? d->signalSender : parent();
+ const QMetaObject *mo = sender->metaObject();
+ int methods = mo->methodCount();
+ for (int ii = 0; ii < methods; ++ii) {
+ QMetaMethod method = mo->method(ii);
+ QString methodName = QLatin1String(method.signature());
+ int idx = methodName.indexOf(QLatin1Char('('));
+ methodName = methodName.left(idx);
+ if (methodName == signalname && (lparen<0 || method.parameterNames() == sigparams)) {
+ sigIdx = ii;
+ break;
+ }
+ }
+ if (sigIdx < 0) {
+ qWarning() << "signal" << d->signal << "not found";
+ return;
+ }
+
+ if (sigparams.isEmpty())
+ d->boundsignal = new QmlBoundSignal(qmlContext(this), d->script, sender, sigIdx, this);
+ else
+ d->boundsignal = new QmlBoundSignalProxy(new QmlContext(qmlContext(this),this), d->script, sender, sigIdx, this);
+ }
+}
+
+void QmlConnection::disconnectIfValid()
+{
+ Q_D(QmlConnection);
+ if (!d->componentcomplete)
+ return;
+ if ((d->signalSender || parent()) && !d->signal.isEmpty() && !d->script.isEmpty()) {
+ // boundsignal must exist
+ // destroy
+ delete d->boundsignal;
+ d->boundsignal = 0;
+ }
+}
+
+void QmlConnection::componentComplete()
+{
+ Q_D(QmlConnection);
+ d->componentcomplete=true;
+ connectIfValid();
+}
+
+
+/*!
+ \qmlproperty string Connection::script
+ This property holds the JavaScript executed whenever the signal is sent.
+
+ This is the default attribute of Connection.
+*/
+
+/*!
+ \property QmlConnection::script
+ \brief the JavaScript executed whenever the signal is sent.
+*/
+QString QmlConnection::script() const
+{
+ Q_D(const QmlConnection);
+ return d->script;
+}
+
+void QmlConnection::setScript(const QString& script)
+{
+ Q_D(QmlConnection);
+ if ((d->signalSender || parent()) && !d->signal.isEmpty()) {
+ if (d->script.isEmpty()) {
+ // mustn't exist - create
+ d->script = script;
+ connectIfValid();
+ } else {
+ // must exist - update
+ d->script = script;
+ d->boundsignal->setExpression(script);
+ }
+ } else {
+ d->script = script;
+ }
+}
+
+/*!
+ \qmlproperty string Connection::signal
+ This property holds the signal from the sender to which the script is attached.
+
+ The signal must have its formal parameter names given in parentheses:
+
+ \qml
+Connection {
+ signal: "clicked(x,y)"
+ script: { ... }
+}
+ \endqml
+*/
+
+/*!
+ \property QmlConnection::signal
+ \brief the signal from the sender to which the script is attached.
+*/
+QString QmlConnection::signal() const
+{
+ Q_D(const QmlConnection);
+ return d->signal;
+}
+
+void QmlConnection::setSignal(const QString& sig)
+{
+ Q_D(QmlConnection);
+ if (d->signal == sig)
+ return;
+ disconnectIfValid();
+ d->signal = sig;
+ connectIfValid();
+}
+
+QML_DEFINE_TYPE(QmlConnection,Connection);
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlconnection.h b/src/declarative/util/qmlconnection.h
new file mode 100644
index 0000000..c943092
--- /dev/null
+++ b/src/declarative/util/qmlconnection.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCONNECTION_H
+#define QMLCONNECTION_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtDeclarative/qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlBoundSignal;
+class QmlContext;
+class QmlConnectionPrivate;
+class Q_DECLARATIVE_EXPORT QmlConnection : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlConnection)
+
+ Q_INTERFACES(QmlParserStatus);
+ Q_CLASSINFO("DefaultProperty", "script");
+ Q_PROPERTY(QObject *sender READ signalSender WRITE setSignalSender);
+ Q_PROPERTY(QString script READ script WRITE setScript);
+ Q_PROPERTY(QString signal READ signal WRITE setSignal);
+
+public:
+ QmlConnection(QObject *parent=0);
+ ~QmlConnection();
+
+ QObject *signalSender() const;
+ void setSignalSender(QObject *);
+ QString script() const;
+ void setScript(const QString&);
+ QString signal() const;
+ void setSignal(const QString&);
+
+private:
+ void disconnectIfValid();
+ void connectIfValid();
+ void componentComplete();
+};
+QML_DECLARE_TYPE(QmlConnection);
+
+#endif
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmldatetimeformatter.cpp b/src/declarative/util/qmldatetimeformatter.cpp
new file mode 100644
index 0000000..94b87ee
--- /dev/null
+++ b/src/declarative/util/qmldatetimeformatter.cpp
@@ -0,0 +1,368 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldatetimeformatter.h"
+#include "private/qobject_p.h"
+#include <QtCore/qlocale.h>
+
+QT_BEGIN_NAMESPACE
+//TODO: may need optimisation as the QDateTime member may not be needed?
+// be able to set a locale?
+
+class QmlDateTimeFormatterPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlDateTimeFormatter)
+public:
+ QmlDateTimeFormatterPrivate() : locale(QLocale::system()), longStyle(false), classComplete(true) {}
+
+ void updateText();
+
+ QDateTime dateTime;
+ QDate date;
+ QTime time;
+ QLocale locale;
+ QString dateTimeText;
+ QString dateText;
+ QString timeText;
+ QString dateTimeFormat; //set for convienience?
+ QString dateFormat;
+ QString timeFormat;
+ bool longStyle;
+ bool classComplete;
+};
+
+/*!
+ \qmlclass DateTimeFormatter QmlDateTimeFormatter
+ \brief The DateTimeFormatter allows you to control the format of a date string.
+
+ \code
+ DateTimeFormatter { id: Formatter; date: System.date }
+ Text { text: Formatter.dateText }
+ \endcode
+
+ By default, the text properties (dateText, timeText, and dateTimeText) will return the
+ date and time using the current system locale's format.
+*/
+
+/*!
+ \internal
+ \class QmlDateTimeFormatter
+ \ingroup group_utility
+ \brief The QmlDateTimeFormatter class allows you to format a date string.
+*/
+
+QmlDateTimeFormatter::QmlDateTimeFormatter(QObject *parent)
+: QObject(*(new QmlDateTimeFormatterPrivate), parent)
+{
+}
+
+QmlDateTimeFormatter::~QmlDateTimeFormatter()
+{
+}
+
+/*!
+ \qmlproperty string DateTimeFormatter::dateText
+ \qmlproperty string DateTimeFormatter::timeText
+ \qmlproperty string DateTimeFormatter::dateTimeText
+
+ Formatted text representations of the \c date, \c time,
+ and \c {date and time}, respectively.
+
+ If there is no explictly specified format the DateTimeFormatter
+ will use the system locale's default 'short' setting.
+
+ \code
+ // specify source date (assuming today is February 19, 2009)
+ DateTimeFormatter { id: formatter; dateTime: Today.date }
+
+ // display the full date and time
+ Text { text: formatter.dateText }
+ \endcode
+
+ Would be equivalent to the following for a US English locale:
+
+ \code
+ // display the date
+ Text { text: "2/19/09" }
+ \endcode
+*/
+QString QmlDateTimeFormatter::dateTimeText() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateTimeText;
+}
+
+QString QmlDateTimeFormatter::dateText() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateText;
+}
+
+QString QmlDateTimeFormatter::timeText() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->timeText;
+}
+
+/*!
+ \qmlproperty date DateTimeFormatter::date
+ \qmlproperty time DateTimeFormatter::time
+ \qmlproperty datetime DateTimeFormatter::dateTime
+
+ The source date and time to be used by the formatter.
+
+ \code
+ // setting the date and time
+ DateTimeFormatter { date: System.date; time: System.time }
+ \endcode
+
+ For convienience it is possible to set the datetime property to set both the date and the time.
+ \code
+ // setting the datetime
+ DateTimeFormatter { dateTime: System.dateTime }
+ \endcode
+
+ There can only be one instance of date and time per formatter; if date, time, and dateTime are all
+ set the actual date and time used is not guaranteed.
+
+ \note If no date is set, dateTimeText will be just the date;
+ If no time is set, the dateTimeText will be just the time.
+
+*/
+QDate QmlDateTimeFormatter::date() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->date;
+}
+
+QTime QmlDateTimeFormatter::time() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->time;
+}
+
+QDateTime QmlDateTimeFormatter::dateTime() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateTime;
+}
+
+/*!
+ \qmlproperty string DateTimeFormatter::dateFormat
+ \qmlproperty string DateTimeFormatter::timeFormat
+ \qmlproperty string DateTimeFormatter::dateTimeFormat
+
+ Specifies a custom format which the DateTime Formatter can use.
+
+ If there is no explictly specified format the DateTimeFormatter
+ will use the system locale's default 'short' setting.
+
+ The text's format may be modified by setting:
+ \list
+ \i \c dateFormat
+ \i \c timeFormat
+ \i \c dateTimeFormat
+ \endlist
+
+ If only the format for date is defined, the time and dateTime formats will be defined
+ as the system locale default and likewise for the others.
+
+ Syntax for the format is based on the QDateTime::toString() formatting options.
+
+ \code
+ // Format the date such that the dateText is: '1997-12-12'
+ DateTimeFormatter { id: formatter; dateTime: Today.dateTime; formatDate: "yyyy-MM-d" }
+ \endcode
+
+ Assigning an empty string to a particular format will reset it.
+*/
+QString QmlDateTimeFormatter::dateTimeFormat() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateTimeFormat;
+}
+
+QString QmlDateTimeFormatter::dateFormat() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->dateFormat;
+}
+
+QString QmlDateTimeFormatter::timeFormat() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->timeFormat;
+}
+
+/*!
+ \qmlproperty bool DateTimeFormatter::longStyle
+
+ This property causes the formatter to use the system locale's long format rather than short format
+ by default.
+
+ This setting is off by default.
+*/
+bool QmlDateTimeFormatter::longStyle() const
+{
+ Q_D(const QmlDateTimeFormatter);
+ return d->longStyle;
+}
+
+void QmlDateTimeFormatter::setDateTime(const QDateTime &dateTime)
+{
+ Q_D(QmlDateTimeFormatter);
+ if (d->dateTime == dateTime)
+ return;
+ d->dateTime = dateTime;
+ d->date = d->dateTime.date();
+ d->time = d->dateTime.time();
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setTime(const QTime &time)
+{
+ Q_D(QmlDateTimeFormatter);
+ if (d->dateTime.time() == time)
+ return;
+ d->time = time;
+ d->dateTime.setTime(time);
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setDate(const QDate &date)
+{
+ Q_D(QmlDateTimeFormatter);
+ if (d->dateTime.date() == date)
+ return;
+ d->date = date;
+ bool clearTime = d->dateTime.time().isValid() ? false : true; //because setting date generates default time
+ d->dateTime.setDate(date);
+ if (clearTime)
+ d->dateTime.setTime(QTime());
+ d->updateText();
+}
+
+//DateTime formatting may be a combination of date and time?
+void QmlDateTimeFormatter::setDateTimeFormat(const QString &format)
+{
+ Q_D(QmlDateTimeFormatter);
+ //no format checking
+ d->dateTimeFormat = format;
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setDateFormat(const QString &format)
+{
+ Q_D(QmlDateTimeFormatter);
+ //no format checking
+ d->dateFormat = format;
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setTimeFormat(const QString &format)
+{
+ Q_D(QmlDateTimeFormatter);
+ //no format checking
+ d->timeFormat = format;
+ d->updateText();
+}
+
+void QmlDateTimeFormatter::setLongStyle(bool longStyle)
+{
+ Q_D(QmlDateTimeFormatter);
+ d->longStyle = longStyle;
+ d->updateText();
+}
+
+void QmlDateTimeFormatterPrivate::updateText()
+{
+ Q_Q(QmlDateTimeFormatter);
+ if (!classComplete)
+ return;
+
+ QString str;
+ QString str1;
+ QString str2;
+
+ Qt::DateFormat defaultFormat = longStyle ? Qt::SystemLocaleLongDate : Qt::SystemLocaleShortDate;
+
+ if (dateFormat.isEmpty())
+ str1 = date.toString(defaultFormat);
+ else
+ str1 = date.toString(dateFormat);
+
+ if (timeFormat.isEmpty())
+ str2 = time.toString(defaultFormat);
+ else
+ str2 = time.toString(timeFormat);
+
+ if (dateTimeFormat.isEmpty())
+ str = dateTime.toString(defaultFormat);
+ //else if (!formatTime.isEmpty() && !formatDate.isEmpty())
+ // str = str1 + QLatin1Char(' ') + str2;
+ else
+ str = dateTime.toString(dateTimeFormat);
+
+ if (dateTimeText == str && dateText == str1 && timeText == str2)
+ return;
+
+ dateTimeText = str;
+ dateText = str1;
+ timeText = str2;
+
+ emit q->textChanged();
+}
+
+void QmlDateTimeFormatter::classBegin()
+{
+ Q_D(QmlDateTimeFormatter);
+ d->classComplete = false;
+}
+
+void QmlDateTimeFormatter::classComplete()
+{
+ Q_D(QmlDateTimeFormatter);
+ d->classComplete = true;
+ d->updateText();
+}
+
+QML_DEFINE_TYPE(QmlDateTimeFormatter, DateTimeFormatter);
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmldatetimeformatter.h b/src/declarative/util/qmldatetimeformatter.h
new file mode 100644
index 0000000..3421f8c
--- /dev/null
+++ b/src/declarative/util/qmldatetimeformatter.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDATETIMEFORMATTER_H
+#define QMLDATETIMEFORMATTER_H
+
+#include <QtCore/qdatetime.h>
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlDateTimeFormatterPrivate;
+class Q_DECLARATIVE_EXPORT QmlDateTimeFormatter : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(QString dateText READ dateText NOTIFY textChanged)
+ Q_PROPERTY(QString timeText READ timeText NOTIFY textChanged)
+ Q_PROPERTY(QString dateTimeText READ dateTimeText NOTIFY textChanged)
+ Q_PROPERTY(QDate date READ date WRITE setDate)
+ Q_PROPERTY(QTime time READ time WRITE setTime)
+ Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime)
+ Q_PROPERTY(QString dateFormat READ dateFormat WRITE setDateFormat)
+ Q_PROPERTY(QString timeFormat READ timeFormat WRITE setTimeFormat)
+ Q_PROPERTY(QString dateTimeFormat READ dateTimeFormat WRITE setDateTimeFormat)
+ Q_PROPERTY(bool longStyle READ longStyle WRITE setLongStyle)
+public:
+ QmlDateTimeFormatter(QObject *parent=0);
+ ~QmlDateTimeFormatter();
+
+ QString dateTimeText() const;
+ QString dateText() const;
+ QString timeText() const;
+
+ QDate date() const;
+ void setDate(const QDate &);
+
+ QTime time() const;
+ void setTime(const QTime &);
+
+ QDateTime dateTime() const;
+ void setDateTime(const QDateTime &);
+
+ QString dateTimeFormat() const;
+ void setDateTimeFormat(const QString &);
+
+ QString dateFormat() const;
+ void setDateFormat(const QString &);
+
+ QString timeFormat() const;
+ void setTimeFormat(const QString &);
+
+ bool longStyle() const;
+ void setLongStyle(bool);
+
+ virtual void classBegin();
+ virtual void classComplete();
+
+Q_SIGNALS:
+ void textChanged();
+
+private:
+ Q_DISABLE_COPY(QmlDateTimeFormatter)
+ Q_DECLARE_PRIVATE(QmlDateTimeFormatter)
+};
+
+QML_DECLARE_TYPE(QmlDateTimeFormatter);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/util/qmlfollow.cpp b/src/declarative/util/qmlfollow.cpp
new file mode 100644
index 0000000..8e5ae69
--- /dev/null
+++ b/src/declarative/util/qmlfollow.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <limits.h>
+#include <QtCore/qdebug.h>
+#include "private/qobject_p.h"
+#include "qmlfollow.h"
+#include "private/qmlanimation_p.h"
+
+
+QT_BEGIN_NAMESPACE
+QML_DEFINE_TYPE(QmlFollow,Follow);
+
+class QmlFollowPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlFollow)
+public:
+ QmlFollowPrivate()
+ : sourceValue(0), maxVelocity(0), lastTime(0)
+ , mass(1.0), spring(0.), damping(0.), velocity(0), epsilon(0.005), enabled(true), mode(Track), clock(this) {}
+
+ QmlMetaProperty property;
+ qreal currentValue;
+ qreal sourceValue;
+ qreal maxVelocity;
+ qreal velocityms;
+ int lastTime;
+ qreal mass;
+ qreal spring;
+ qreal damping;
+ qreal velocity;
+ qreal epsilon;
+ bool enabled;
+
+ enum Mode {
+ Track,
+ Velocity,
+ Spring
+ };
+ Mode mode;
+
+ void tick(int);
+ void updateMode();
+ void start();
+ void stop();
+
+ QTickAnimationProxy<QmlFollowPrivate, &QmlFollowPrivate::tick> clock;
+};
+
+void QmlFollowPrivate::tick(int time)
+{
+ Q_Q(QmlFollow);
+
+ int elapsed = time - lastTime;
+ if (!elapsed)
+ return;
+ if (mode == Spring) {
+ if (elapsed < 10) // capped at 100fps.
+ return;
+ // Real men solve the spring DEs using RK4.
+ // We'll do something much simpler which gives a result that looks fine.
+ int count = (elapsed+5) / 10;
+ for (int i = 0; i < count; ++i) {
+ qreal diff = sourceValue - currentValue;
+ velocity = velocity + spring * diff - damping * velocity;
+ // The following line supports mass. Not sure its worth the extra divisions.
+ // velocity = velocity + spring / mass * diff - damping / mass * velocity;
+ if (maxVelocity > 0.) {
+ // limit velocity
+ if (velocity > maxVelocity)
+ velocity = maxVelocity;
+ else if (velocity < -maxVelocity)
+ velocity = -maxVelocity;
+ }
+ currentValue += velocity * 10.0 / 1000.0;
+ }
+ if (qAbs(velocity) < epsilon && qAbs(sourceValue - currentValue) < epsilon) {
+ velocity = 0.0;
+ currentValue = sourceValue;
+ clock.stop();
+ }
+ lastTime = time - (elapsed - count * 10);
+ } else {
+ qreal moveBy = elapsed * velocityms;
+ qreal diff = sourceValue - currentValue;
+ if (diff > 0) {
+ currentValue += moveBy;
+ if (currentValue > sourceValue) {
+ currentValue = sourceValue;
+ clock.stop();
+ }
+ } else {
+ currentValue -= moveBy;
+ if (currentValue < sourceValue) {
+ currentValue = sourceValue;
+ clock.stop();
+ }
+ }
+ lastTime = time;
+ }
+ emit q->valueChanged(currentValue);
+ property.write(currentValue);
+}
+
+void QmlFollowPrivate::updateMode()
+{
+ if (spring == 0. && maxVelocity == 0.)
+ mode = Track;
+ else if (spring > 0.)
+ mode = Spring;
+ else
+ mode = Velocity;
+}
+
+void QmlFollowPrivate::start()
+{
+ if (!enabled)
+ return;
+
+ if (mode == QmlFollowPrivate::Track) {
+ currentValue = sourceValue;
+ property.write(currentValue);
+ } else if (sourceValue != currentValue && clock.state() != QAbstractAnimation::Running) {
+ lastTime = 0;
+ clock.start(); // infinity??
+ }
+}
+
+void QmlFollowPrivate::stop()
+{
+ clock.stop();
+}
+
+/*!
+ \qmlclass Follow QmlFollow
+ \brief The Follow element allows a property to track a value.
+
+ In example below, Rect2 will follow Rect1 moving with a velocity of up to 200:
+ \code
+ Rect {
+ id: Rect1
+ width: 20; height: 20
+ color: "#00ff00"
+ y: 200 //initial value
+ y: SequentialAnimation {
+ running: true
+ repeat: true
+ NumericAnimation {
+ to: 200
+ easing: "easeOutBounce(amplitude:100)"
+ duration: 2000
+ }
+ PauseAnimation { duration: 1000 }
+ }
+ }
+ Rect {
+ id: Rect2
+ x: Rect1.width
+ width: 20; height: 20
+ color: "#ff0000"
+ y: Follow { source: Rect1.y; velocity: 200 }
+ }
+ \endcode
+*/
+
+QmlFollow::QmlFollow(QObject *parent)
+: QmlPropertyValueSource(*(new QmlFollowPrivate),parent)
+{
+}
+
+QmlFollow::~QmlFollow()
+{
+}
+
+void QmlFollow::setTarget(const QmlMetaProperty &property)
+{
+ Q_D(QmlFollow);
+ d->property = property;
+ d->currentValue = property.read().toDouble();
+}
+
+qreal QmlFollow::sourceValue() const
+{
+ Q_D(const QmlFollow);
+ return d->sourceValue;
+}
+
+/*!
+ \qmlproperty qreal Follow::source
+ This property holds the source value which will be tracked.
+
+ Bind to a property in order to track its changes.
+*/
+
+void QmlFollow::setSourceValue(qreal value)
+{
+ Q_D(QmlFollow);
+ d->sourceValue = value;
+ d->start();
+}
+
+/*!
+ \qmlproperty qreal Follow::velocity
+ This property holds the maximum velocity allowed when tracking the source.
+*/
+
+qreal QmlFollow::velocity() const
+{
+ Q_D(const QmlFollow);
+ return d->maxVelocity;
+}
+
+void QmlFollow::setVelocity(qreal velocity)
+{
+ Q_D(QmlFollow);
+ d->maxVelocity = velocity;
+ d->velocityms = velocity / 1000.0;
+ d->updateMode();
+}
+
+/*!
+ \qmlproperty qreal Follow::spring
+ This property holds the spring constant
+
+ The spring constant describes how strongly the target is pulled towards the
+ source. Setting spring to 0 turns off spring tracking. Useful values 0 - 5.0
+
+ When a spring constant is set and the velocity property is greater than 0,
+ velocity limits the maximum speed.
+*/
+qreal QmlFollow::spring() const
+{
+ Q_D(const QmlFollow);
+ return d->spring;
+}
+
+void QmlFollow::setSpring(qreal spring)
+{
+ Q_D(QmlFollow);
+ d->spring = spring;
+ d->updateMode();
+}
+
+/*!
+ \qmlproperty qreal Follow::damping
+ This property holds the spring damping constant
+
+ The damping constant describes how quickly a sprung follower comes to rest.
+ Useful range is 0 - 1.0
+*/
+qreal QmlFollow::damping() const
+{
+ Q_D(const QmlFollow);
+ return d->damping;
+}
+
+void QmlFollow::setDamping(qreal damping)
+{
+ Q_D(QmlFollow);
+ if (damping > 1.)
+ damping = 1.;
+
+ d->damping = damping;
+}
+
+
+/*!
+ \qmlproperty qreal Follow::epsilon
+ This property holds the spring epsilon
+
+ The epsilon is the rate and amount of change in the value which is close enough
+ to 0 to be considered equal to zero. This will depend on the usage of the value.
+ For pixel positions, 0.25 would suffice. For scale, 0.005 will suffice.
+
+ The default is 0.005. Small performance improvements can result in tuning this
+ value.
+*/
+qreal QmlFollow::epsilon() const
+{
+ Q_D(const QmlFollow);
+ return d->epsilon;
+}
+
+void QmlFollow::setEpsilon(qreal epsilon)
+{
+ Q_D(QmlFollow);
+ d->epsilon = epsilon;
+}
+
+/*!
+ \qmlproperty qreal Follow::followValue
+ The current value.
+*/
+
+/*!
+ \qmlproperty bool Follow::enabled
+ This property holds whether the target will track the source.
+*/
+bool QmlFollow::enabled() const
+{
+ Q_D(const QmlFollow);
+ return d->enabled;
+}
+
+void QmlFollow::setEnabled(bool enabled)
+{
+ Q_D(QmlFollow);
+ d->enabled = enabled;
+ if (enabled)
+ d->start();
+ else
+ d->stop();
+}
+
+qreal QmlFollow::value() const
+{
+ Q_D(const QmlFollow);
+ return d->currentValue;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlfollow.h b/src/declarative/util/qmlfollow.h
new file mode 100644
index 0000000..bd9363a
--- /dev/null
+++ b/src/declarative/util/qmlfollow.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLFOLLOW_H
+#define QMLFOLLOW_H
+
+#include <qmlpropertyvaluesource.h>
+#include <qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlFollowPrivate;
+class Q_DECLARATIVE_EXPORT QmlFollow : public QmlPropertyValueSource,
+ public QmlParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlFollow)
+ Q_INTERFACES(QmlParserStatus)
+
+ Q_PROPERTY(qreal source READ sourceValue WRITE setSourceValue);
+ Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity);
+ Q_PROPERTY(qreal spring READ spring WRITE setSpring);
+ Q_PROPERTY(qreal damping READ damping WRITE setDamping);
+ Q_PROPERTY(qreal epsilon READ epsilon WRITE setEpsilon);
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled);
+
+ Q_PROPERTY(qreal followValue READ value NOTIFY valueChanged);
+public:
+ QmlFollow(QObject *parent=0);
+ ~QmlFollow();
+
+ virtual void setTarget(const QmlMetaProperty &);
+
+ qreal sourceValue() const;
+ void setSourceValue(qreal value);
+ qreal velocity() const;
+ void setVelocity(qreal velocity);
+ qreal spring() const;
+ void setSpring(qreal spring);
+ qreal damping() const;
+ void setDamping(qreal damping);
+ qreal epsilon() const;
+ void setEpsilon(qreal epsilon);
+ bool enabled() const;
+ void setEnabled(bool enabled);
+
+ qreal value() const;
+
+Q_SIGNALS:
+ void valueChanged(qreal);
+};
+
+QML_DECLARE_TYPE(QmlFollow);
+
+
+#endif // QFXFOLLOW_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmlfont.cpp b/src/declarative/util/qmlfont.cpp
new file mode 100644
index 0000000..9f3225a
--- /dev/null
+++ b/src/declarative/util/qmlfont.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qobject_p.h"
+#include "qfont.h"
+#include "qmlfont.h"
+
+
+QT_BEGIN_NAMESPACE
+class QmlFontPrivate : public QObjectPrivate
+{
+public:
+ QFont font;
+};
+
+QML_DEFINE_TYPE(QmlFont,Font);
+
+/*!
+ \internal
+ \class QmlFont
+ \ingroup group_utility
+ \brief The QmlFont class provides a font used for drawing text on a QFxView.
+*/
+QmlFont::QmlFont(QObject *parent)
+ : QObject(*(new QmlFontPrivate), parent)
+{
+}
+
+QmlFont::~QmlFont()
+{
+}
+
+/*!
+ \property QmlFont::family
+ \brief the family of the font.
+*/
+QString QmlFont::family() const
+{
+ Q_D(const QmlFont);
+ return d->font.family();
+}
+
+void QmlFont::setFamily(const QString &family)
+{
+ Q_D(QmlFont);
+ d->font.setFamily(family);
+ emit updated();
+}
+
+/*!
+ \property QmlFont::bold
+ \brief whether the font should be bold.
+*/
+bool QmlFont::bold() const
+{
+ Q_D(const QmlFont);
+ return d->font.bold();
+}
+
+void QmlFont::setBold(bool b)
+{
+ Q_D(QmlFont);
+ d->font.setBold(b);
+ emit updated();
+}
+
+/*!
+ \property QmlFont::italic
+ \brief whether the font should be italic.
+*/
+bool QmlFont::italic() const
+{
+ Q_D(const QmlFont);
+ return d->font.italic();
+}
+
+void QmlFont::setItalic(bool b)
+{
+ Q_D(QmlFont);
+ d->font.setItalic(b);
+ emit updated();
+}
+
+/*!
+ \property QmlFont::size
+ \brief the size of the font in points.
+*/
+qreal QmlFont::size() const
+{
+ Q_D(const QmlFont);
+ return d->font.pointSizeF();
+}
+
+void QmlFont::setSize(qreal size)
+{
+ Q_D(QmlFont);
+ d->font.setPointSizeF(size);
+ emit updated();
+}
+
+/*!
+ \brief Returns a QFont representation of the font.
+*/
+QFont QmlFont::font() const
+{
+ Q_D(const QmlFont);
+ return d->font;
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlfont.h b/src/declarative/util/qmlfont.h
new file mode 100644
index 0000000..b6bce7c
--- /dev/null
+++ b/src/declarative/util/qmlfont.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLFONT_H
+#define QMLFONT_H
+
+#include <QtCore/qobject.h>
+#include <qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlFontPrivate;
+class Q_DECLARATIVE_EXPORT QmlFont : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlFont)
+
+ Q_PROPERTY(QString family READ family WRITE setFamily)
+ Q_PROPERTY(bool bold READ bold WRITE setBold)
+ Q_PROPERTY(bool italic READ italic WRITE setItalic)
+ Q_PROPERTY(qreal size READ size WRITE setSize)
+
+public:
+ QmlFont(QObject *parent=0);
+ ~QmlFont();
+
+ QString family() const;
+ void setFamily(const QString &);
+
+ bool bold() const;
+ void setBold(bool b);
+
+ bool italic() const;
+ void setItalic(bool b);
+
+ qreal size() const;
+ void setSize(qreal size);
+
+ QFont font() const;
+
+Q_SIGNALS:
+ void updated();
+};
+QML_DECLARE_TYPE(QmlFont);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QMLFONT_H
diff --git a/src/declarative/util/qmllistaccessor.cpp b/src/declarative/util/qmllistaccessor.cpp
new file mode 100644
index 0000000..da54b6e
--- /dev/null
+++ b/src/declarative/util/qmllistaccessor.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmllistaccessor.h"
+#include <QStringList>
+#include <qmlmetatype.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlListAccessor::QmlListAccessor()
+: type(Invalid)
+{
+}
+
+QmlListAccessor::~QmlListAccessor()
+{
+}
+
+QVariant QmlListAccessor::list() const
+{
+ return d;
+}
+
+void QmlListAccessor::setList(const QVariant &v)
+{
+ d = v;
+
+ if (!d.isValid()) {
+ type = Invalid;
+ } else if (d.type() == QVariant::StringList) {
+ type = StringList;
+ } else if (d.type() != QVariant::UserType) {
+ type = Instance;
+ } else if (QmlMetaType::isObject(d.userType())) {
+ QObject *data = 0;
+ data = *(QObject **)v.constData();
+ d = QVariant::fromValue(data);
+ type = Instance;
+ } else if (QmlMetaType::isQmlList(d.userType())) {
+ type = QmlList;
+ } else if (QmlMetaType::isList(d.userType())) {
+ type = QList;
+ } else {
+ type = Invalid;
+ d = QVariant();
+ }
+}
+
+int QmlListAccessor::count() const
+{
+ switch(type) {
+ case Invalid:
+ return 0;
+ case StringList:
+ return qvariant_cast<QStringList>(d).count();
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ return li->count();
+ }
+ case QList:
+ return QmlMetaType::listCount(d);
+ case Instance:
+ return 1;
+ }
+
+ return 0;
+}
+
+QVariant QmlListAccessor::at(int idx) const
+{
+ Q_ASSERT(idx >= 0 && idx < count());
+ switch(type) {
+ case Invalid:
+ return QVariant();
+ case StringList:
+ return QVariant::fromValue(qvariant_cast<QStringList>(d).at(idx));
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ void *ptr[1];
+ li->at(idx, ptr);
+ return QmlMetaType::fromObject((QObject*)ptr[0], li->type()); //XXX only handles QObject-derived types
+ }
+ case QList:
+ return QmlMetaType::listAt(d, idx);
+ case Instance:
+ return d;
+ }
+
+ return QVariant();
+}
+
+void QmlListAccessor::append(const QVariant &value)
+{
+ switch(type) {
+ case Invalid:
+ break;
+ case StringList:
+ {
+ const QString &str = value.toString();
+ qvariant_cast<QStringList>(d).append(str);
+ break;
+ }
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ li->append(const_cast<void *>(value.constData())); //XXX
+ break;
+ }
+ case QList:
+ QmlMetaType::append(d, value);
+ break;
+ case Instance:
+ //do nothing
+ break;
+ }
+}
+
+void QmlListAccessor::insert(int index, const QVariant &value)
+{
+ switch(type) {
+ case Invalid:
+ break;
+ case StringList:
+ {
+ const QString &str = value.toString();
+ qvariant_cast<QStringList>(d).insert(index, str);
+ break;
+ }
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ li->insert(index, const_cast<void *>(value.constData())); //XXX
+ break;
+ }
+ case QList:
+ //XXX needs implementation
+ qWarning() << "insert function not yet implemented for QLists";
+ break;
+ case Instance:
+ //XXX do nothing?
+ if (index == 0)
+ setList(value);
+ break;
+ }
+}
+
+void QmlListAccessor::removeAt(int index)
+{
+ switch(type) {
+ case Invalid:
+ break;
+ case StringList:
+ qvariant_cast<QStringList>(d).removeAt(index);
+ break;
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ li->removeAt(index);
+ break;
+ }
+ case QList:
+ //XXX needs implementation
+ qWarning() << "removeAt function not yet implemented for QLists";
+ break;
+ case Instance:
+ //XXX do nothing?
+ if (index == 0)
+ setList(QVariant());
+ break;
+ }
+}
+
+void QmlListAccessor::clear()
+{
+ switch(type) {
+ case Invalid:
+ break;
+ case StringList:
+ qvariant_cast<QStringList>(d).clear();
+ break;
+ case QmlList:
+ {
+ QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)d.constData();
+ li->clear();
+ break;
+ }
+ case QList:
+ QmlMetaType::clear(d);
+ break;
+ case Instance:
+ //XXX what should we do here?
+ setList(QVariant());
+ break;
+ }
+}
+
+bool QmlListAccessor::isValid() const
+{
+ return type != Invalid;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmllistaccessor.h b/src/declarative/util/qmllistaccessor.h
new file mode 100644
index 0000000..29f910d
--- /dev/null
+++ b/src/declarative/util/qmllistaccessor.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLLISTACCESSOR_H
+#define QMLLISTACCESSOR_H
+
+#include <QVariant>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlListAccessor
+{
+public:
+ QmlListAccessor();
+ virtual ~QmlListAccessor();
+
+ QVariant list() const;
+ void setList(const QVariant &);
+
+ bool isValid() const;
+
+ int count() const;
+ QVariant at(int) const;
+
+ virtual void append(const QVariant &);
+ virtual void insert(int, const QVariant &);
+ virtual void removeAt(int);
+ virtual void clear();
+
+private:
+ enum Type { Invalid, StringList, QmlList, QList, Instance };
+ Type type;
+ QVariant d;
+};
+
+#endif // QMLLISTACCESSOR_H
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp
new file mode 100644
index 0000000..8184bda
--- /dev/null
+++ b/src/declarative/util/qmllistmodel.cpp
@@ -0,0 +1,566 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qstack.h>
+#include <QXmlStreamReader>
+#include <private/qmlcustomparser_p.h>
+#include "qmlopenmetaobject.h"
+#include <qmlcontext.h>
+#include <qmlbindablevalue.h>
+#include "qmllistmodel.h"
+
+QT_BEGIN_NAMESPACE
+
+#define DATA_ROLE_ID 1
+#define DATA_ROLE_NAME "data"
+
+struct ListInstruction
+{
+ enum { Push, Pop, Value, Set } type;
+ int dataIdx;
+};
+
+struct ListModelData
+{
+ int dataOffset;
+ int instrCount;
+ ListInstruction *instructions() const { return (ListInstruction *)((char *)this + sizeof(ListModelData)); }
+};
+
+Q_DECLARE_METATYPE(QListModelInterface *);
+
+/*!
+ \qmlclass ListModel
+ \brief The ListModel element defines a free-form list data source.
+
+ The ListModel is a simple heirarchy of items containing data roles.
+ For example:
+
+ \code
+ ListModel {
+ id: FruitModel
+ ListElement {
+ name: "Apple"
+ cost: 2.45
+ }
+ ListElement {
+ name: "Orange"
+ cost: 3.25
+ }
+ ListElement {
+ name: "Banana"
+ cost: 1.95
+ }
+ }
+ \endcode
+
+ Item roles (properties) must begin with a lower-case letter. The above example defines a
+ ListModel containing three items, with the roles "name" and "cost".
+
+ The defined model can be used in views such as ListView:
+ \code
+ Component {
+ id: FruitDelegate
+ Item {
+ width: 200; height: 50
+ Text { text: name }
+ Text { text: '$'+cost; anchors.right: parent.right }
+ }
+ }
+
+ ListView {
+ model: FruitModel
+ delegate: FruitDelegate
+ anchors.fill: parent
+ }
+ \endcode
+
+ It is possible for roles to contain list data. In the example below we create a list of fruit attributes:
+
+ \code
+ ListModel {
+ id: FruitModel
+ ListElement {
+ name: "Apple"
+ cost: 2.45
+ attributes: [
+ ListElement { description: "Core" },
+ ListElement { description: "Deciduous" }
+ ]
+ }
+ ListElement {
+ name: "Orange"
+ cost: 3.25
+ attributes: [
+ ListElement { description: "Citrus" }
+ ]
+ }
+ ListElement {
+ name: "Banana"
+ cost: 1.95
+ attributes: [
+ ListElement { description: "Tropical" }
+ ListElement { description: "Seedless" }
+ ]
+ }
+ }
+ \endcode
+
+ The delegate below will list all the fruit attributes:
+ \code
+ Component {
+ id: FruitDelegate
+ Item {
+ width: 200; height: 50
+ Text { id: Name; text: name }
+ Text { text: '$'+cost; anchors.right: parent.right }
+ HorizontalLayout {
+ anchors.top: Name.bottom
+ spacing: 5
+ Text { text: "Attributes:" }
+ Repeater {
+ dataSource: attributes
+ Component { Text { text: description } }
+ }
+ }
+ }
+ }
+ \endcode
+
+*/
+
+struct ModelNode;
+class ListModel : public QListModelInterface
+{
+ Q_OBJECT
+public:
+ ListModel(QObject *parent=0);
+
+ virtual QList<int> roles() const;
+ virtual QString toString(int role) const;
+ Q_PROPERTY(int count READ count);
+ virtual int count() const;
+ virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+
+private:
+ QVariant valueForNode(ModelNode *) const;
+ mutable QStringList roleStrings;
+ friend class ListModelParser;
+ friend struct ModelNode;
+
+ void checkRoles() const;
+ void addRole(const QString &) const;
+ mutable bool _rolesOk;
+ ModelNode *_root;
+};
+
+class ModelObject : public QObject
+{
+ Q_OBJECT
+public:
+ ModelObject(ModelNode *);
+
+ void setValue(const QByteArray &name, const QVariant &val)
+ {
+ _mo->setValue(name, val);
+ }
+
+private:
+ ModelNode *_node;
+ bool _haveProperties;
+ QmlOpenMetaObject *_mo;
+};
+
+struct ModelNode
+{
+ ModelNode();
+ ~ModelNode();
+ QString className;
+
+ QList<QVariant> values;
+ QHash<QString, ModelNode *> properties;
+
+ ListModel *model() {
+ if (!modelCache) {
+ modelCache = new ListModel;
+ modelCache->_root = this;
+ }
+ return modelCache;
+ }
+
+ ModelObject *object() {
+ if (!objectCache) {
+ objectCache = new ModelObject(this);
+ QHash<QString, ModelNode *>::iterator it;
+ for (it = properties.begin(); it != properties.end(); ++it) {
+ if (!(*it)->values.isEmpty())
+ objectCache->setValue(it.key().toLatin1(), (*it)->values.first());
+ }
+ }
+ return objectCache;
+ }
+
+ ListModel *modelCache;
+ ModelObject *objectCache;
+};
+Q_DECLARE_METATYPE(ModelNode *);
+
+ModelObject::ModelObject(ModelNode *node)
+: _node(node), _haveProperties(false), _mo(new QmlOpenMetaObject(this))
+{
+}
+
+ListModel::ListModel(QObject *parent)
+: QListModelInterface(parent), _rolesOk(false), _root(0)
+{
+}
+
+void ListModel::checkRoles() const
+{
+ if (_rolesOk)
+ return;
+
+ for (int ii = 0; ii < _root->values.count(); ++ii) {
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(ii));
+ if (node) {
+ foreach (const QString &role, node->properties.keys())
+ addRole(role);
+ }
+ }
+
+ _rolesOk = true;
+}
+
+void ListModel::addRole(const QString &role) const
+{
+ if (!roleStrings.contains(role))
+ roleStrings << role;
+}
+
+QList<int> ListModel::roles() const
+{
+ checkRoles();
+ QList<int> rv;
+ for (int ii = 0; ii < roleStrings.count(); ++ii)
+ rv << ii;
+ return rv;
+}
+
+QString ListModel::toString(int role) const
+{
+ checkRoles();
+ if (role < roleStrings.count())
+ return roleStrings.at(role);
+ else
+ return QString();
+}
+
+QVariant ListModel::valueForNode(ModelNode *node) const
+{
+ QObject *rv = 0;
+
+ if (!node->properties.isEmpty()) {
+ // Object
+ rv = node->object();
+ } else if (node->values.count() == 0) {
+ // Invalid
+ return QVariant();
+ } else if (node->values.count() == 1) {
+ // Value
+ QVariant &var = node->values[0];
+ ModelNode *valueNode = qvariant_cast<ModelNode *>(var);
+ if (valueNode) {
+ if (!valueNode->properties.isEmpty())
+ rv = valueNode->object();
+ else
+ rv = valueNode->model();
+ } else {
+ return var;
+ }
+ } else if (node->values.count() > 1) {
+ // List
+ rv = node->model();
+ }
+
+ if (rv)
+ return QVariant::fromValue(rv);
+ else
+ return QVariant();
+}
+
+QHash<int,QVariant> ListModel::data(int index, const QList<int> &roles) const
+{
+ checkRoles();
+ QHash<int, QVariant> rv;
+ if (index >= count())
+ return rv;
+
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ if (!node)
+ return rv;
+
+ for (int ii = 0; ii < roles.count(); ++ii) {
+ const QString &roleString = roleStrings.at(roles.at(ii));
+
+ QHash<QString, ModelNode *>::ConstIterator iter =
+ node->properties.find(roleString);
+ if (iter != node->properties.end()) {
+ ModelNode *row = *iter;
+ rv.insert(roles.at(ii), valueForNode(row));
+ }
+ }
+
+ return rv;
+}
+
+int ListModel::count() const
+{
+ if (!_root) return 0;
+ return _root->values.count();
+}
+
+class ListModelParser : public QmlCustomParser
+{
+public:
+ QByteArray compile(const QList<QmlCustomParserProperty> &, bool *ok);
+ bool compileProperty(const QmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data);
+ void setCustomData(QObject *, const QByteArray &);
+};
+
+bool ListModelParser::compileProperty(const QmlCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data)
+{
+ QList<QVariant> values = prop.assignedValues();
+ for(int ii = 0; ii < values.count(); ++ii) {
+ const QVariant &value = values.at(ii);
+
+ if(value.userType() == qMetaTypeId<QmlCustomParserNode>()) {
+ QmlCustomParserNode node =
+ qvariant_cast<QmlCustomParserNode>(value);
+
+ {
+ ListInstruction li;
+ li.type = ListInstruction::Push;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ QList<QmlCustomParserProperty> props = node.properties();
+ for(int jj = 0; jj < props.count(); ++jj) {
+ const QmlCustomParserProperty &nodeProp = props.at(jj);
+ if(nodeProp.name() == "")
+ return false;
+
+ ListInstruction li;
+ int ref = data.count();
+ data.append(nodeProp.name());
+ data.append('\0');
+ li.type = ListInstruction::Set;
+ li.dataIdx = ref;
+ instr << li;
+
+ if(!compileProperty(nodeProp, instr, data))
+ return false;
+
+ li.type = ListInstruction::Pop;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ {
+ ListInstruction li;
+ li.type = ListInstruction::Pop;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ } else {
+
+ int ref = data.count();
+ QByteArray d = value.toString().toLatin1();
+ d.append('\0');
+ data.append(d);
+
+ ListInstruction li;
+ li.type = ListInstruction::Value;
+ li.dataIdx = ref;
+ instr << li;
+
+ }
+ }
+
+ return true;
+}
+
+QByteArray ListModelParser::compile(const QList<QmlCustomParserProperty> &customProps, bool *ok)
+{
+ *ok = true;
+ QList<ListInstruction> instr;
+ QByteArray data;
+
+ for(int ii = 0; ii < customProps.count(); ++ii) {
+ const QmlCustomParserProperty &prop = customProps.at(ii);
+ if(prop.name() != "") { // isn't default property
+ *ok = false;
+ return QByteArray();
+ }
+
+ if(!compileProperty(prop, instr, data)) {
+ *ok = false;
+ return QByteArray();
+ }
+ }
+
+ int size = sizeof(ListModelData) +
+ instr.count() * sizeof(ListInstruction) +
+ data.count();
+
+ QByteArray rv;
+ rv.resize(size);
+
+ ListModelData *lmd = (ListModelData *)rv.data();
+ lmd->dataOffset = sizeof(ListModelData) +
+ instr.count() * sizeof(ListInstruction);
+ lmd->instrCount = instr.count();
+ for (int ii = 0; ii < instr.count(); ++ii)
+ lmd->instructions()[ii] = instr.at(ii);
+ ::memcpy(rv.data() + lmd->dataOffset, data.constData(), data.count());
+
+ return rv;
+}
+
+void ListModelParser::setCustomData(QObject *obj, const QByteArray &d)
+{
+ ListModel *rv = static_cast<ListModel *>(obj);
+
+ ModelNode *root = new ModelNode;
+ rv->_root = root;
+ QStack<ModelNode *> nodes;
+ nodes << root;
+
+ const ListModelData *lmd = (const ListModelData *)d.constData();
+ const char *data = ((const char *)lmd) + lmd->dataOffset;
+
+ for (int ii = 0; ii < lmd->instrCount; ++ii) {
+ const ListInstruction &instr = lmd->instructions()[ii];
+
+ switch(instr.type) {
+ case ListInstruction::Push:
+ {
+ ModelNode *n = nodes.top();
+ ModelNode *n2 = new ModelNode;
+ n->values << qVariantFromValue(n2);
+ nodes.push(n2);
+ }
+ break;
+
+ case ListInstruction::Pop:
+ nodes.pop();
+ break;
+
+ case ListInstruction::Value:
+ {
+ ModelNode *n = nodes.top();
+ n->values.append(QByteArray(data + instr.dataIdx));
+ }
+ break;
+
+ case ListInstruction::Set:
+ {
+ ModelNode *n = nodes.top();
+ ModelNode *n2 = new ModelNode;
+ n->properties.insert(QLatin1String(data + instr.dataIdx), n2);
+ nodes.push(n2);
+ }
+ break;
+ }
+ }
+}
+
+QML_DECLARE_TYPE(ListModel);
+QML_DEFINE_CUSTOM_TYPE(ListModel, ListModel, ListModelParser);
+
+// ### FIXME
+class ListElement : public QObject
+{
+Q_OBJECT
+};
+QML_DECLARE_TYPE(ListElement);
+QML_DEFINE_TYPE(ListElement,ListElement);
+
+static void dump(ModelNode *node, int ind)
+{
+ QByteArray indentBa(ind * 4, ' ');
+ const char *indent = indentBa.constData();
+
+ for (int ii = 0; ii < node->values.count(); ++ii) {
+ ModelNode *subNode = qvariant_cast<ModelNode *>(node->values.at(ii));
+ if (subNode) {
+ qWarning().nospace() << indent << "Sub-node " << ii << ": class " << subNode->className;
+ dump(subNode, ind + 1);
+ } else {
+ qWarning().nospace() << indent << "Sub-node " << ii << ": " << node->values.at(ii).toString();
+ }
+ }
+
+ for (QHash<QString, ModelNode *>::ConstIterator iter = node->properties.begin(); iter != node->properties.end(); ++iter) {
+ qWarning().nospace() << indent << "Property " << iter.key() << ":";
+ dump(iter.value(), ind + 1);
+ }
+}
+
+ModelNode::ModelNode()
+: modelCache(0), objectCache(0)
+{
+}
+
+ModelNode::~ModelNode()
+{
+ qDeleteAll(properties);
+ for (int ii = 0; ii < values.count(); ++ii) {
+ ModelNode *node = qvariant_cast<ModelNode *>(values.at(ii));
+ if (node) { delete node; node = 0; }
+ }
+ if (modelCache) { delete modelCache; modelCache = 0; }
+}
+
+QT_END_NAMESPACE
+#include "qmllistmodel.moc"
diff --git a/src/declarative/util/qmllistmodel.h b/src/declarative/util/qmllistmodel.h
new file mode 100644
index 0000000..36aa009
--- /dev/null
+++ b/src/declarative/util/qmllistmodel.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLLISTMODEL_H
+#define QMLLISTMODEL_H
+
+#include <QObject>
+#include <qfxglobal.h>
+#include <QStringList>
+#include <QHash>
+#include <QList>
+#include <QVariant>
+#include <qml.h>
+#include <qlistmodelinterface.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLLISTMODEL_H
diff --git a/src/declarative/util/qmlnullablevalue_p.h b/src/declarative/util/qmlnullablevalue_p.h
new file mode 100644
index 0000000..f16ddd6
--- /dev/null
+++ b/src/declarative/util/qmlnullablevalue_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLNULLABLEVALUE_P_H
+#define QMLNULLABLEVALUE_P_H
+
+template<typename T>
+struct QmlNullableValue
+{
+ QmlNullableValue()
+ : isNull(true), value(T()) {}
+ QmlNullableValue(const QmlNullableValue<T> &o)
+ : isNull(o.isNull), value(o.value) {}
+ QmlNullableValue(const T &t)
+ : isNull(false), value(t) {}
+ QmlNullableValue<T> &operator=(const T &t)
+ { isNull = false; value = t; return *this; }
+ QmlNullableValue<T> &operator=(const QmlNullableValue<T> &o)
+ { isNull = o.isNull; value = o.value; return *this; }
+ operator T() const { return value; }
+
+ void invalidate() { isNull = true; }
+ bool isValid() const { return !isNull; }
+ bool isNull;
+ T value;
+};
+
+#endif // QMLNULLABLEVALUE_P_H
+
diff --git a/src/declarative/util/qmlopenmetaobject.cpp b/src/declarative/util/qmlopenmetaobject.cpp
new file mode 100644
index 0000000..d0dd817
--- /dev/null
+++ b/src/declarative/util/qmlopenmetaobject.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlopenmetaobject.h"
+#include "private/qmetaobjectbuilder_p.h"
+#include <QDebug>
+
+
+QT_BEGIN_NAMESPACE
+
+class QmlOpenMetaObjectPrivate
+{
+public:
+ QmlOpenMetaObjectPrivate() : parent(0), mem(0) {}
+
+ bool autoCreate;
+ QAbstractDynamicMetaObject *parent;
+ int propertyOffset;
+ int signalOffset;
+ QList<QVariant> data;
+ QHash<QByteArray, int> names;
+ QMetaObjectBuilder mob;
+ QMetaObject *mem;
+ QObject *object;
+};
+
+QmlOpenMetaObject::QmlOpenMetaObject(QObject *obj, bool automatic)
+: d(new QmlOpenMetaObjectPrivate)
+{
+ d->autoCreate = automatic;
+ d->object = obj;
+
+ d->mob.setSuperClass(obj->metaObject());
+ d->mob.setClassName(obj->metaObject()->className());
+ d->mob.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ if (op->metaObject)
+ d->mob.setSuperClass(op->metaObject);
+
+ d->mem = d->mob.toMetaObject();
+ *static_cast<QMetaObject *>(this) = *d->mem;
+ op->metaObject = this;
+ d->propertyOffset = propertyOffset();
+ d->signalOffset = methodOffset();
+}
+
+QmlOpenMetaObject::~QmlOpenMetaObject()
+{
+ if (d->parent)
+ delete d->parent;
+ qFree(d->mem);
+ delete d;
+}
+
+int QmlOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if (( c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty)
+ && id >= d->propertyOffset) {
+ int propId = id - d->propertyOffset;
+ if (c == QMetaObject::ReadProperty) {
+ propertyRead(propId);
+ *reinterpret_cast<QVariant *>(a[0]) = d->data[propId];
+ } else if (c == QMetaObject::WriteProperty) {
+ if (d->data[propId] != *reinterpret_cast<QVariant *>(a[0])) {
+ propertyWrite(propId);
+ d->data[propId] = *reinterpret_cast<QVariant *>(a[0]);
+ activate(d->object, d->signalOffset + propId, 0);
+ }
+ }
+ return -1;
+ } else {
+ if (d->parent)
+ return d->parent->metaCall(c, id, a);
+ else
+ return d->object->qt_metacall(c, id, a);
+ }
+}
+
+QVariant QmlOpenMetaObject::value(int id) const
+{
+ Q_ASSERT(id >= 0 && id < d->data.count());
+ return d->data.at(id);
+}
+
+void QmlOpenMetaObject::setValue(int id, const QVariant &value)
+{
+ Q_ASSERT(id >= 0 && id < d->data.count());
+ d->data[id] = value;
+ activate(d->object, id + d->signalOffset, 0);
+}
+
+QVariant QmlOpenMetaObject::value(const QByteArray &name) const
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->names.find(name);
+ if (iter == d->names.end())
+ return QVariant();
+
+ return d->data.at(*iter);
+}
+
+void QmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->names.find(name);
+
+ int id = -1;
+ if (iter == d->names.end()) {
+ id = doCreateProperty(name.constData()) - d->propertyOffset;
+ } else {
+ id = *iter;
+ }
+
+ if (d->data[id] == val)
+ return;
+
+ d->data[id] = val;
+ activate(d->object, id + d->signalOffset, 0);
+}
+
+int QmlOpenMetaObject::createProperty(const char *name, const char *)
+{
+ if (d->autoCreate)
+ return doCreateProperty(name);
+ else
+ return -1;
+}
+
+int QmlOpenMetaObject::doCreateProperty(const char *name)
+{
+ int id = d->mob.propertyCount();
+ d->mob.addSignal("__" + QByteArray::number(id) + "()");
+ QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", id);
+ build.setDynamic(true);
+ d->data << propertyCreated(id, build);
+ qFree(d->mem);
+ d->mem = d->mob.toMetaObject();
+ *static_cast<QMetaObject *>(this) = *d->mem;
+ d->names.insert(name, id);
+
+ return d->propertyOffset + id;
+}
+
+void QmlOpenMetaObject::propertyRead(int)
+{
+}
+
+void QmlOpenMetaObject::propertyWrite(int)
+{
+}
+
+QVariant QmlOpenMetaObject::propertyCreated(int, QMetaPropertyBuilder &)
+{
+ return QVariant();
+}
+
+int QmlOpenMetaObject::count() const
+{
+ return d->data.count();
+}
+
+QByteArray QmlOpenMetaObject::name(int idx) const
+{
+ Q_ASSERT(idx >= 0 && idx < d->data.count());
+
+ return d->mob.property(idx).name();
+}
+
+QObject *QmlOpenMetaObject::object() const
+{
+ return d->object;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlopenmetaobject.h b/src/declarative/util/qmlopenmetaobject.h
new file mode 100644
index 0000000..f842f96
--- /dev/null
+++ b/src/declarative/util/qmlopenmetaobject.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLOPENMETAOBJECT_H
+#define QMLOPENMETAOBJECT_H
+
+#include <QMetaObject>
+#include <QtCore/private/qobject_p.h>
+#include <QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlOpenMetaObjectPrivate;
+class QMetaPropertyBuilder;
+class Q_DECLARATIVE_EXPORT QmlOpenMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QmlOpenMetaObject(QObject *, bool = true);
+ ~QmlOpenMetaObject();
+
+ QVariant value(const QByteArray &) const;
+ void setValue(const QByteArray &, const QVariant &);
+ QVariant value(int) const;
+ void setValue(int, const QVariant &);
+
+ int count() const;
+ QByteArray name(int) const;
+
+ QObject *object() const;
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+ virtual int createProperty(const char *, const char *);
+
+ virtual void propertyRead(int);
+ virtual void propertyWrite(int);
+ virtual QVariant propertyCreated(int, QMetaPropertyBuilder &);
+
+private:
+ int doCreateProperty(const char *);
+
+ QmlOpenMetaObjectPrivate *d;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QMLOPENMETAOBJECT_H
diff --git a/src/declarative/util/qmlpackage.cpp b/src/declarative/util/qmlpackage.cpp
new file mode 100644
index 0000000..aa7ed38
--- /dev/null
+++ b/src/declarative/util/qmlpackage.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qobject_p.h"
+#include "qmlpackage.h"
+
+
+QT_BEGIN_NAMESPACE
+class QmlPackagePrivate : public QObjectPrivate
+{
+public:
+ QmlPackagePrivate() {}
+
+ QmlConcreteList<QObject *> dataList;
+};
+
+class QmlPackageAttached : public QObject
+{
+Q_OBJECT
+public:
+ QmlPackageAttached(QObject *parent);
+ virtual ~QmlPackageAttached();
+
+ Q_PROPERTY(QString name READ name WRITE setName);
+ QString name() const;
+ void setName(const QString &n);
+
+ static QHash<QObject *, QmlPackageAttached *> attached;
+private:
+ QString _name;
+};
+
+QHash<QObject *, QmlPackageAttached *> QmlPackageAttached::attached;
+
+QmlPackageAttached::QmlPackageAttached(QObject *parent)
+: QObject(parent)
+{
+ attached.insert(parent, this);
+}
+
+QmlPackageAttached::~QmlPackageAttached()
+{
+ attached.remove(parent());
+}
+
+QString QmlPackageAttached::name() const
+{
+ return _name;
+}
+
+void QmlPackageAttached::setName(const QString &n)
+{
+ _name = n;
+}
+
+QmlPackage::QmlPackage(QObject *parent)
+ : QObject(*(new QmlPackagePrivate), parent)
+{
+}
+
+QmlPackage::~QmlPackage()
+{
+}
+
+QmlList<QObject *> *QmlPackage::data()
+{
+ Q_D(QmlPackage);
+ return &d->dataList;
+}
+
+bool QmlPackage::hasPart(const QString &name)
+{
+ Q_D(QmlPackage);
+ for (int ii = 0; ii < d->dataList.count(); ++ii) {
+ QObject *obj = d->dataList.at(ii);
+ QmlPackageAttached *a = QmlPackageAttached::attached.value(obj);
+ if (a && a->name() == name)
+ return true;
+ }
+ return false;
+}
+
+QObject *QmlPackage::part(const QString &name)
+{
+ Q_D(QmlPackage);
+ if (name.isEmpty() && !d->dataList.isEmpty())
+ return d->dataList.at(0);
+
+ for (int ii = 0; ii < d->dataList.count(); ++ii) {
+ QObject *obj = d->dataList.at(ii);
+ QmlPackageAttached *a = QmlPackageAttached::attached.value(obj);
+ if (a && a->name() == name)
+ return obj;
+ }
+
+ if (name == QLatin1String("default") && !d->dataList.isEmpty())
+ return d->dataList.at(0);
+
+ return 0;
+}
+
+QObject *QmlPackage::qmlAttachedProperties(QObject *o)
+{
+ return new QmlPackageAttached(o);
+}
+
+QML_DEFINE_TYPE(QmlPackage, Package);
+
+QT_END_NAMESPACE
+#include "qmlpackage.moc"
diff --git a/src/declarative/util/qmlpackage.h b/src/declarative/util/qmlpackage.h
new file mode 100644
index 0000000..6652b98
--- /dev/null
+++ b/src/declarative/util/qmlpackage.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPACKAGE_H
+#define QMLPACKAGE_H
+
+#include <qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+/*****************************************************************************
+ *****************************************************************************
+ XXX Experimental
+ *****************************************************************************
+*****************************************************************************/
+
+class QmlPackagePrivate;
+class QmlPackage : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlPackage)
+
+ Q_CLASSINFO("DefaultProperty", "data");
+ Q_PROPERTY(QmlList<QObject *> *data READ data SCRIPTABLE false);
+
+public:
+ QmlPackage(QObject *parent=0);
+ virtual ~QmlPackage();
+
+ QmlList<QObject *> *data();
+
+ QObject *part(const QString & = QString());
+ bool hasPart(const QString &);
+
+ static QObject *qmlAttachedProperties(QObject *);
+};
+QML_DECLARE_TYPE(QmlPackage);
+
+#endif // QMLPACKAGE_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp
new file mode 100644
index 0000000..d986b7a
--- /dev/null
+++ b/src/declarative/util/qmlscript.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qmlbindablevalue.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <private/qobject_p.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qdebug.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptcontext.h>
+#include <QtScript/qscriptengine.h>
+#include <private/qmlnullablevalue_p.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlcontext_p.h>
+#include "qmlscript.h"
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QtDeclarative/qmlinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QmlScriptPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlScript);
+
+public:
+ QmlScriptPrivate() : reply(0) {}
+
+ void addScriptToEngine(const QString &, const QString &fileName=QString());
+
+ QString script;
+ QString source;
+ QNetworkReply *reply;
+ QUrl url;
+};
+
+/*!
+ \qmlclass Script QmlScript
+ \brief The Script element adds JavaScript snippets.
+ \ingroup group_utility
+
+ QmlScript is used to add convenient JavaScript "glue" methods to
+ your Qt Declarative application or component. While you can have any JavaScript code
+ within a QmlScript, it is best to limit yourself to defining functions.
+
+ \qml
+ Script {
+ function debugMyComponent() {
+ print(text.text);
+ print(otherinterestingitem.property);
+ }
+ }
+ MouseRegion { onClicked: debugMyComponent() }
+ \endqml
+
+ \note QmlScript executes JavaScript as soon as it is specified.
+ When defining a component, this may be before the execution context is
+ fully specified. As a result some properties or items may not be
+ accessible. By limiting your JavaScript to defining functions that are
+ only executed later once the context is fully defined, this problem is
+ avoided.
+*/
+
+QML_DEFINE_TYPE(QmlScript,Script);
+QmlScript::QmlScript(QObject *parent) : QObject(*(new QmlScriptPrivate), parent)
+{
+}
+
+/*!
+ \qmlproperty string Script::script
+ \default
+ JavaScript code to execute.
+*/
+/*!
+ \property QmlScript::script
+ \brief a script snippet.
+*/
+QString QmlScript::script() const
+{
+ Q_D(const QmlScript);
+ return d->script;
+}
+
+void QmlScript::setScript(const QString &script)
+{
+ Q_D(QmlScript);
+ d->script = script;
+ d->addScriptToEngine(d->script);
+}
+
+/*!
+ \qmlproperty string Script::source
+
+ Setting this property causes the Script element to read JavaScript code from
+ the file specified.
+ */
+/*!
+ \property QmlScript::source
+ \brief the path to a script file.
+*/
+QString QmlScript::source() const
+{
+ Q_D(const QmlScript);
+ return d->source;
+}
+
+void QmlScript::setSource(const QString &source)
+{
+ Q_D(QmlScript);
+ if (d->source == source)
+ return;
+ d->source = source;
+ d->url = qmlContext(this)->resolvedUrl(source);
+
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ if (d->url.scheme() == QLatin1String("file")) {
+ QFile file(d->url.toLocalFile());
+ file.open(QIODevice::ReadOnly);
+ QByteArray ba = file.readAll();
+ d->addScriptToEngine(QString::fromUtf8(ba), d->source);
+ } else
+#endif
+ {
+ QNetworkRequest req(d->url);
+ req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+ d->reply = qmlEngine(this)->networkAccessManager()->get(req);
+ QObject::connect(d->reply, SIGNAL(finished()),
+ this, SLOT(replyFinished()));
+ }
+}
+
+void QmlScript::replyFinished()
+{
+ Q_D(QmlScript);
+ if (!d->reply->error()) {
+ QByteArray ba = d->reply->readAll();
+ d->addScriptToEngine(QString::fromUtf8(ba), d->source);
+ }
+ d->reply->deleteLater();
+ d->reply = 0;
+}
+
+void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &fileName)
+{
+ Q_Q(QmlScript);
+ QmlEngine *engine = qmlEngine(q);
+ QmlContext *context = qmlContext(q);
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+
+ QScriptContext *currentContext = engine->scriptEngine()->currentContext();
+ QScriptValueList oldScopeChain = currentContext->scopeChain();
+ QScriptValue oldact = currentContext->activationObject();
+
+ for (int i = 0; i < oldScopeChain.size(); ++i) {
+ currentContext->popScope();
+ }
+ for (int i = context->d_func()->scopeChain.size() - 1; i > -1; --i) {
+ currentContext->pushScope(context->d_func()->scopeChain.at(i));
+ }
+
+ currentContext->setActivationObject(context->d_func()->scopeChain.at(0));
+
+ QScriptValue val = scriptEngine->evaluate(script, fileName);
+ if (scriptEngine->hasUncaughtException()) {
+ if (scriptEngine->uncaughtException().isError()){
+ QScriptValue exception = scriptEngine->uncaughtException();
+ if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){
+ qWarning() << exception.property(QLatin1String("fileName")).toString()
+ << scriptEngine->uncaughtExceptionLineNumber()
+ << exception.toString();
+
+ } else {
+ qmlInfo(q) << exception.toString();
+ }
+ }
+ }
+
+ currentContext->setActivationObject(oldact);
+
+ for (int i = 0; i < context->d_func()->scopeChain.size(); ++i)
+ currentContext->popScope();
+
+ for (int i = oldScopeChain.size() - 1; i > -1; --i)
+ currentContext->pushScope(oldScopeChain.at(i));
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlscript.h b/src/declarative/util/qmlscript.h
new file mode 100644
index 0000000..8047a88
--- /dev/null
+++ b/src/declarative/util/qmlscript.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSCRIPT_H
+#define QMLSCRIPT_H
+
+#include <qfxglobal.h>
+#include <QtCore/qobject.h>
+#include "qml.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlScriptPrivate;
+class Q_DECLARATIVE_EXPORT QmlScript : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlScript);
+
+ Q_PROPERTY(QString script READ script WRITE setScript);
+ Q_PROPERTY(QString source READ source WRITE setSource);
+ Q_CLASSINFO("DefaultProperty", "script");
+
+public:
+ QmlScript(QObject *parent=0);
+
+ QString script() const;
+ void setScript(const QString &);
+
+ QString source() const;
+ void setSource(const QString &);
+
+private Q_SLOTS:
+ void replyFinished();
+};
+QML_DECLARE_TYPE(QmlScript);
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif
diff --git a/src/declarative/util/qmlsetproperties.cpp b/src/declarative/util/qmlsetproperties.cpp
new file mode 100644
index 0000000..9b5a58e
--- /dev/null
+++ b/src/declarative/util/qmlsetproperties.cpp
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qobject_p.h"
+#include "qmlopenmetaobject.h"
+#include "qmlsetproperties.h"
+#include <QtCore/qdebug.h>
+#include <QtDeclarative/qmlinfo.h>
+
+
+QT_BEGIN_NAMESPACE
+class QmlSetPropertiesMetaObject : public QmlOpenMetaObject
+{
+public:
+ QmlSetPropertiesMetaObject(QObject *);
+
+protected:
+ virtual void propertyRead(int);
+ virtual void propertyWrite(int);
+};
+
+class QmlSetPropertiesProxyObject : public QObject
+{
+Q_OBJECT
+public:
+ QmlSetPropertiesProxyObject(QObject *);
+
+ QmlSetPropertiesMetaObject *fxMetaObject() const { return _mo; }
+private:
+ QmlSetPropertiesMetaObject *_mo;
+};
+
+QmlSetPropertiesProxyObject::QmlSetPropertiesProxyObject(QObject *parent)
+: QObject(parent), _mo(new QmlSetPropertiesMetaObject(this))
+{
+}
+
+QmlSetPropertiesMetaObject::QmlSetPropertiesMetaObject(QObject *obj)
+: QmlOpenMetaObject(obj)
+{
+}
+
+void QmlSetPropertiesMetaObject::propertyRead(int id)
+{
+ if (!value(id).isValid())
+ setValue(id, QVariant::fromValue((QObject *)new QmlSetPropertiesProxyObject(object())));
+
+ QmlOpenMetaObject::propertyRead(id);
+}
+
+void QmlSetPropertiesMetaObject::propertyWrite(int id)
+{
+ if (value(id).userType() == qMetaTypeId<QObject *>()) {
+ QObject *val = qvariant_cast<QObject *>(value(id));
+ QmlSetPropertiesProxyObject *proxy = qobject_cast<QmlSetPropertiesProxyObject *>(val);
+ if (proxy) {
+ setValue(id, QVariant());
+ delete proxy;
+ }
+ }
+ QmlOpenMetaObject::propertyWrite(id);
+}
+
+/*!
+ \qmlclass SetProperties QmlSetProperties
+ \brief The SetProperties element describes new property values for a state.
+
+ SetProperties is a convenience element for changing many properties on a single
+ object. It allows you to specify the property names and values similar to how
+ you normally would specify them for the actual item:
+
+ \code
+ SetProperties {
+ target: myRect
+ x: 52
+ y: 300
+ width: 48
+ }
+ \endcode
+
+ \c target is a property of \c SetProperties, so if the property you want to change
+ is named \e target you will have to use \l SetProperty instead. You should also
+ use \l SetProperty if you want to update the binding for a property,
+ as SetProperties does not support this.
+*/
+
+/*!
+ \internal
+ \class QmlSetProperties
+ \brief The QmlSetProperties class describes new property values for a state.
+
+ \ingroup group_states
+
+ QmlSetProperties is a convenience class for changing many properties on a single
+ object. It allows you to specify the property names and values similar to how
+ you normally would specify them for the actual item:
+
+ \code
+ SetProperties {
+ target: myRect
+ x: 52
+ y: 300
+ width: 48
+ }
+ \endcode
+
+ \c target is a property of \c SetProperties, so if the property you want to change
+ is named \e target you will have to use QmlSetProperty instead. You should also use QmlSetProperty
+ if you want to update the binding for a property, as QmlSetProperties does not support this.
+
+ \sa QmlSetProperty
+*/
+
+class QmlSetPropertiesPrivate : public QObjectPrivate
+{
+public:
+ QmlSetPropertiesPrivate() : obj(0), mo(0) {}
+
+ QObject *obj;
+ QmlSetPropertiesMetaObject *mo;
+};
+
+QML_DEFINE_TYPE(QmlSetProperties,SetProperties);
+QmlSetProperties::QmlSetProperties()
+ : QmlStateOperation(*(new QmlSetPropertiesPrivate))
+{
+ Q_D(QmlSetProperties);
+ d->mo = new QmlSetPropertiesMetaObject(this);
+}
+
+QmlSetProperties::QmlSetProperties(QObject *parent)
+ : QmlStateOperation(*(new QmlSetPropertiesPrivate), parent)
+{
+ Q_D(QmlSetProperties);
+ d->mo = new QmlSetPropertiesMetaObject(this);
+}
+
+QmlSetProperties::~QmlSetProperties()
+{
+}
+
+/*!
+ \qmlproperty Object SetProperties::target
+ This property holds the object that the properties to change belong to
+*/
+
+/*!
+ \property QmlSetProperties::target
+ \brief the object that the properties to change belong to
+*/
+QObject *QmlSetProperties::object()
+{
+ Q_D(QmlSetProperties);
+ return d->obj;
+}
+
+void QmlSetProperties::setObject(QObject *o)
+{
+ Q_D(QmlSetProperties);
+ d->obj = o;
+}
+
+QmlSetProperties::ActionList
+QmlSetProperties::doAction(QmlSetPropertiesMetaObject *metaObject,
+ QObject *object)
+{
+ ActionList list;
+
+ for (int ii = 0; ii < metaObject->count(); ++ii) {
+
+ QByteArray name = metaObject->name(ii);
+ QVariant value = metaObject->value(ii);
+
+ QmlSetPropertiesProxyObject *po = qobject_cast<QmlSetPropertiesProxyObject *>(qvariant_cast<QObject *>(value));
+
+ QmlMetaProperty prop(object, QLatin1String(name));
+
+ if (po) {
+ QObject *objVal = QmlMetaType::toQObject(prop.read());
+ if (!objVal) {
+ qmlInfo(this) << object->metaObject()->className()
+ << "has no object property named" << name;
+ continue;
+ }
+
+ list << doAction(po->fxMetaObject(), objVal);
+ } else if (!prop.isValid()) {
+ qmlInfo(this) << object->metaObject()->className()
+ << "has no property named" << name;
+ continue;
+ } else if (!prop.isWritable()) {
+ qmlInfo(this) << object->metaObject()->className()
+ << name << "is not writable, and cannot be set.";
+ continue;
+ } else {
+ //append action
+ Action a;
+ a.property = prop;
+ a.fromValue = prop.read();
+ a.toValue = value;
+
+ list << a;
+ }
+ }
+
+ return list;
+}
+
+QmlSetProperties::ActionList QmlSetProperties::actions()
+{
+ Q_D(QmlSetProperties);
+ if (!d->obj)
+ return ActionList();
+
+ return doAction(d->mo, d->obj);
+}
+
+QT_END_NAMESPACE
+#include "qmlsetproperties.moc"
diff --git a/src/declarative/util/qmlsetproperties.h b/src/declarative/util/qmlsetproperties.h
new file mode 100644
index 0000000..456b672
--- /dev/null
+++ b/src/declarative/util/qmlsetproperties.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSETPROPERTIES_H
+#define QMLSETPROPERTIES_H
+
+#include <qmlstateoperations.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlSetPropertiesMetaObject;
+class QmlSetPropertiesPrivate;
+class Q_DECLARATIVE_EXPORT QmlSetProperties : public QmlStateOperation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlSetProperties);
+
+ Q_PROPERTY(QObject *target READ object WRITE setObject);
+
+public:
+ QmlSetProperties();
+ QmlSetProperties(QObject *parent);
+ ~QmlSetProperties();
+
+ QObject *object();
+ void setObject(QObject *);
+
+ virtual ActionList actions();
+
+private:
+ ActionList doAction(QmlSetPropertiesMetaObject *, QObject *);
+ //QmlSetProperties::ActionList appendDotActions(const QVariant &, const QVariant &);
+};
+QML_DECLARE_TYPE(QmlSetProperties);
+
+#endif // QMLSETPROPERTIES_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp
new file mode 100644
index 0000000..194cc1b
--- /dev/null
+++ b/src/declarative/util/qmlstate.cpp
@@ -0,0 +1,472 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltransition.h"
+#include "qmlstategroup.h"
+#include "qmlstate_p.h"
+#include "qmlbindablevalue.h"
+#include "qmlstateoperations.h"
+#include "qmlanimation.h"
+#include "qmlanimation_p.h"
+#include "qmlstate.h"
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG);
+
+Action::Action() : bv(0), event(0), actionDone(false)
+{
+}
+
+ActionEvent::~ActionEvent()
+{
+}
+
+QString ActionEvent::name() const
+{
+ return QString();
+}
+
+void ActionEvent::execute()
+{
+}
+
+/*!
+ \internal
+*/
+QmlStateOperation::QmlStateOperation(QObjectPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ \qmlclass State
+ \brief The State element defines configurations of objects and properties.
+
+ A state is specified as a set of batched changes from the default configuration.
+
+ Note that setting the state of an object from within another state of the same object is
+ inadvisible. Not only would this have the same effect as going directly to the second state
+ it may cause the program to crash.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+/*!
+ \internal
+ \class QmlState
+ \brief The QmlState class allows you to define configurations of objects and properties.
+
+ \ingroup group_states
+
+ QmlState allows you to specify a state as a set of batched changes from the default
+ configuration.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+QML_DEFINE_TYPE(QmlState,State);
+QmlState::QmlState(QObject *parent)
+: QObject(*(new QmlStatePrivate), parent)
+{
+}
+
+QmlState::~QmlState()
+{
+}
+
+/*!
+ \qmlproperty string State::name
+ This property holds the name of the state
+
+ Each state should have a unique name.
+*/
+
+/*!
+ \property QmlState::name
+ \brief the name of the state
+
+ Each state should have a unique name.
+*/
+QString QmlState::name() const
+{
+ Q_D(const QmlState);
+ return d->name;
+}
+
+void QmlState::setName(const QString &n)
+{
+ Q_D(QmlState);
+ d->name = n;
+}
+
+bool QmlState::isWhenKnown() const
+{
+ Q_D(const QmlState);
+ return d->when != 0;
+}
+
+/*!
+ \qmlproperty bool State::when
+ This property holds when the state should be applied
+
+ This should be set to an expression that evaluates to true when you want the state to
+ be applied.
+*/
+
+/*!
+ \property QmlState::when
+ \brief when the state should be applied
+
+ This should be set to an expression that evaluates to true when you want the state to
+ be applied.
+*/
+QmlBindableValue *QmlState::when() const
+{
+ Q_D(const QmlState);
+ return d->when;
+}
+
+void QmlState::setWhen(QmlBindableValue *when)
+{
+ Q_D(QmlState);
+ d->when = when;
+ if (d->group)
+ d->group->updateAutoState();
+}
+
+/*!
+ \qmlproperty string State::extends
+ This property holds the state that this state extends
+
+ The state being extended is treated as the base state in regards to
+ the changes specified by the extending state.
+*/
+
+/*!
+ \property QmlState::extends
+ \brief the state that this state extends
+
+ The state being extended is treated as the base state in regards to
+ the changes specified by the extending state.
+
+ \sa operations
+*/
+QString QmlState::extends() const
+{
+ Q_D(const QmlState);
+ return d->extends;
+}
+
+void QmlState::setExtends(const QString &extends)
+{
+ Q_D(QmlState);
+ d->extends = extends;
+}
+
+/*!
+ \qmlproperty list<StateOperation> State::operations
+ This property holds the changes to apply for this state
+ \default
+
+ By default these changes are applied against the default state. If the state
+ extends another state, then the changes are applied against the state being
+ extended.
+*/
+
+/*!
+ \property QmlState::operations
+ \brief the changes to apply for this state
+
+ By default these changes are applied against the default state. If the state
+ extends another state, then the changes are applied against the state being
+ extended.
+*/
+QmlList<QmlStateOperation *> *QmlState::operations()
+{
+ Q_D(QmlState);
+ return &d->operations;
+}
+
+QmlState &QmlState::operator<<(QmlStateOperation *op)
+{
+ Q_D(QmlState);
+ d->operations.append(op);
+ return *this;
+}
+
+#if 0
+static void dump(const QmlStateOperation::ActionList &list)
+{
+ if (!QString(getenv("STATE_DEBUG")).isEmpty())
+ return;
+
+ for (int ii = 0; ii < list.count(); ++ii) {
+ const Action &action = list.at(ii);
+ qWarning() << action.property.object << action.property.name << action.toValue;
+ }
+}
+#endif
+
+void QmlStatePrivate::applyBindings()
+{
+ foreach(const Action &action, bindingsList) {
+ if (action.bv && !action.toBinding.isEmpty()) {
+ action.bv->setExpression(action.toBinding);
+ }
+ }
+}
+
+void QmlStatePrivate::complete()
+{
+ Q_Q(QmlState);
+ //apply bindings (now that all transitions are complete)
+ applyBindings();
+
+ for (int ii = 0; ii < reverting.count(); ++ii) {
+ for (int jj = 0; jj < revertList.count(); ++jj) {
+ if (revertList.at(jj).property == reverting.at(ii)) {
+ revertList.removeAt(jj);
+ break;
+ }
+ }
+ }
+ reverting.clear();
+
+ for (int ii = 0; ii < completeList.count(); ++ii) {
+ const QmlMetaProperty &prop = completeList.at(ii).property;
+ prop.write(completeList.at(ii).value);
+ }
+
+ completeList.clear();
+ transition = 0;
+ emit q->completed();
+}
+
+QmlStateOperation::ActionList QmlStatePrivate::generateActionList(QmlStateGroup *group) const
+{
+ QmlStateOperation::ActionList applyList;
+ if (inState)
+ return applyList;
+
+ inState = true;
+
+ if (!extends.isEmpty()) {
+ QList<QmlState *> states = group->states();
+ for (int ii = 0; ii < states.count(); ++ii)
+ if (states.at(ii)->name() == extends)
+ applyList = static_cast<QmlStatePrivate*>(states.at(ii)->d_ptr)->generateActionList(group);
+ }
+
+ foreach(QmlStateOperation *op, operations)
+ applyList << op->actions();
+
+ inState = false;
+ return applyList;
+}
+
+QmlStateGroup *QmlState::stateGroup() const
+{
+ Q_D(const QmlState);
+ return d->group;
+}
+
+void QmlState::setStateGroup(QmlStateGroup *group)
+{
+ Q_D(QmlState);
+ d->group = group;
+}
+
+void QmlState::cancel()
+{
+ Q_D(QmlState);
+ if (d->transition) {
+ d->transition->stop(); //XXX this could potentially trigger a complete in rare circumstances
+ d->transition = 0;
+ }
+}
+
+void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *revert)
+{
+ Q_D(QmlState);
+
+ cancel();
+ if (revert)
+ revert->cancel();
+ d->revertList.clear();
+ d->reverting.clear();
+ d->bindingsList.clear();
+
+ if (revert)
+ d->revertList = static_cast<QmlStatePrivate*>(revert->d_ptr)->revertList;
+ QmlStateOperation::RevertActionList additionalReverts;
+
+ QmlStateOperation::ActionList applyList = d->generateActionList(group);
+
+ for (int ii = 0; ii < applyList.count(); ++ii) {
+ const Action &action = applyList.at(ii);
+ if (action.event)
+ continue;
+
+ bool found = false;
+ for (int jj = 0; !found && jj < d->revertList.count(); ++jj) {
+ if (d->revertList.at(jj).property == action.property)
+ found = true;
+ }
+ if (!found) {
+ RevertAction r(action);
+ additionalReverts << r;
+ }
+ }
+ for (int ii = 0; ii < d->revertList.count(); ++ii) {
+ bool found = false;
+ for (int jj = 0; !found && jj < applyList.count(); ++jj) {
+ const Action &action = applyList.at(jj);
+ if (action.property == d->revertList.at(ii).property)
+ found = true;
+ }
+ if (!found) {
+ QVariant cur = d->revertList.at(ii).property.read();
+ Action a;
+ a.property = d->revertList.at(ii).property;
+ a.fromValue = cur;
+ a.toValue = d->revertList.at(ii).value;
+ a.toBinding = d->revertList.at(ii).binding;
+ if (!a.toBinding.isEmpty()) {
+ a.fromBinding = d->revertList.at(ii).bv->expression();
+ a.bv = d->revertList.at(ii).bv;
+ }
+ applyList << a;
+ d->reverting << d->revertList.at(ii).property;
+ }
+ }
+ d->revertList << additionalReverts;
+
+ //apply all changes, and work out any ending positions for bindings
+ //then rewind all changes and proceed as normal
+ //### 4 foreach loops!
+ ////////////////////////////////////////////////////////////////////
+ foreach(const Action &action, applyList) {
+ if (stateChangeDebug())
+ qWarning() << " Action:" << action.property.object() << action.property.name() << action.toValue;
+
+ if (action.bv && !action.toBinding.isEmpty()) {
+ d->bindingsList << action;
+ action.bv->clearExpression();
+ }
+ }
+
+ if (!d->bindingsList.isEmpty()) {
+ foreach(const Action &action, applyList) {
+ if (action.bv && !action.toBinding.isEmpty()) {
+ action.bv->setExpression(action.toBinding);
+ } else if (!action.event) {
+ action.property.write(action.toValue);
+ }
+ }
+
+ for (int ii = 0; ii < applyList.size(); ++ii) {
+ Action *action = &applyList[ii];
+ if (action->event)
+ continue;
+
+ const QmlMetaProperty &prop = action->property;
+ if (action->bv && !action->toBinding.isEmpty()) {
+ action->toValue = prop.read();
+ }
+ }
+
+ foreach(const Action &action, applyList) {
+ if (action.event)
+ continue;
+
+ if (action.bv && !action.toBinding.isEmpty())
+ action.bv->clearExpression();
+ action.property.write(action.fromValue);
+ }
+ }
+ ////////////////////////////////////////////////////////////////////
+
+ QmlStateOperation::ActionList modList = applyList;
+ QList<QmlMetaProperty> touched;
+ d->completeList.clear();
+ if (trans) {
+ d->transition = trans;
+ trans->prepare(modList, touched, this);
+ for (int ii = 0; ii < modList.count(); ++ii) {
+ const Action &action = modList.at(ii);
+
+ if (action.event) {
+ if (action.actionDone) {
+ modList.removeAt(ii);
+ --ii;
+ }
+ } else {
+ if (action.toValue != action.fromValue) {
+ d->completeList << RevertAction(action, false);
+ }
+
+ if (touched.contains(action.property)) {
+ modList.removeAt(ii);
+ --ii;
+ }
+ }
+ }
+ }
+
+ foreach(const Action &action, modList) {
+ if (action.event)
+ action.event->execute();
+ else
+ action.property.write(action.toValue);
+ }
+ if (!trans)
+ d->applyBindings(); //### merge into above foreach?
+}
+
+QML_DEFINE_TYPE(QmlStateOperation,StateOperation);
+QmlStateOperation::ActionList QmlStateOperation::actions()
+{
+ return ActionList();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlstate.h b/src/declarative/util/qmlstate.h
new file mode 100644
index 0000000..68c43fa
--- /dev/null
+++ b/src/declarative/util/qmlstate.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTATE_H
+#define QMLSTATE_H
+
+#include <QtCore/qobject.h>
+#include <qfxglobal.h>
+#include <qml.h>
+#include <QSequentialAnimationGroup>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class ActionEvent;
+class QmlBindableValue;
+class Action
+{
+public:
+ Action();
+
+ QmlMetaProperty property;
+ QVariant fromValue;
+ QVariant toValue;
+ QString fromBinding;
+ QString toBinding;
+ QmlBindableValue *bv;
+ ActionEvent *event;
+ bool actionDone;
+};
+
+class ActionEvent
+{
+public:
+ virtual ~ActionEvent();
+ virtual QString name() const;
+ virtual void execute();
+};
+
+class RevertAction
+{
+public:
+ RevertAction(const Action &a, bool from = true) : bv(0)
+ {
+ property = a.property;
+ if (from) {
+ value = a.fromValue;
+ binding = a.fromBinding;
+ } else {
+ value = a.toValue;
+ binding = a.toBinding;
+ }
+ bv = a.bv;
+ }
+
+ QmlMetaProperty property;
+ QVariant value;
+ QString binding;
+ QmlBindableValue *bv;
+};
+
+class QmlStateGroup;
+class Q_DECLARATIVE_EXPORT QmlStateOperation : public QObject
+{
+ Q_OBJECT
+public:
+ QmlStateOperation(QObject *parent = 0)
+ : QObject(parent) {}
+ typedef QList<Action> ActionList;
+ typedef QList<RevertAction> RevertActionList;
+
+ virtual ActionList actions();
+
+protected:
+ QmlStateOperation(QObjectPrivate &dd, QObject *parent = 0);
+};
+QML_DECLARE_TYPE(QmlStateOperation);
+
+typedef QmlStateOperation::ActionList QmlStateActions;
+
+class QmlTransition;
+class QmlTransitionPrivate;
+class QmlStatePrivate;
+class Q_DECLARATIVE_EXPORT QmlState : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName);
+ Q_PROPERTY(QmlBindableValue *when READ when WRITE setWhen);
+ Q_PROPERTY(QString extends READ extends WRITE setExtends);
+ Q_PROPERTY(QmlList<QmlStateOperation *>* operations READ operations);
+ Q_CLASSINFO("DefaultProperty", "operations");
+
+public:
+ QmlState(QObject *parent=0);
+ virtual ~QmlState();
+
+ QString name() const;
+ void setName(const QString &);
+
+ /*'when' is a QmlBindableValue to limit state changes oscillation
+ due to the unpredictable order of evaluation of bound expressions*/
+ bool isWhenKnown() const;
+ QmlBindableValue *when() const;
+ void setWhen(QmlBindableValue *);
+
+ QString extends() const;
+ void setExtends(const QString &);
+
+ QmlList<QmlStateOperation *> *operations();
+ QmlState &operator<<(QmlStateOperation *);
+
+ void apply(QmlStateGroup *, QmlTransition *, QmlState *revert);
+ void cancel();
+
+ QmlStateGroup *stateGroup() const;
+ void setStateGroup(QmlStateGroup *);
+
+Q_SIGNALS:
+ void completed();
+
+private:
+ Q_DECLARE_PRIVATE(QmlState)
+ Q_DISABLE_COPY(QmlState)
+ friend class QmlTransitionPrivate;
+};
+QML_DECLARE_TYPE(QmlState);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLSTATE_H
diff --git a/src/declarative/util/qmlstate_p.h b/src/declarative/util/qmlstate_p.h
new file mode 100644
index 0000000..28e1781
--- /dev/null
+++ b/src/declarative/util/qmlstate_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTATE_P_H
+#define QMLSTATE_P_H
+
+#include <qmlstate.h>
+#include "private/qobject_p.h"
+#include "private/qmlanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlStatePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlState);
+
+public:
+ QmlStatePrivate()
+ : when(0), transition(0), inState(false), group(0) {}
+
+ QString name;
+ QmlBindableValue *when;
+ QmlConcreteList<QmlStateOperation *> operations;
+ QmlTransition *transition;
+ QmlStateOperation::RevertActionList revertList;
+ QList<QmlMetaProperty> reverting;
+ QmlStateOperation::RevertActionList completeList;
+ QmlStateOperation::ActionList bindingsList;
+ QString extends;
+ mutable bool inState;
+ QmlStateGroup *group;
+
+ QmlStateOperation::ActionList generateActionList(QmlStateGroup *) const;
+ void applyBindings();
+ void complete();
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLSTATE_P_H
diff --git a/src/declarative/util/qmlstategroup.cpp b/src/declarative/util/qmlstategroup.cpp
new file mode 100644
index 0000000..cabef63
--- /dev/null
+++ b/src/declarative/util/qmlstategroup.cpp
@@ -0,0 +1,306 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qobject_p.h"
+#include "qmlbindablevalue.h"
+#include "qmlstategroup.h"
+#include "qmltransition.h"
+#include <QtCore/qdebug.h>
+
+
+QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG);
+
+QML_DEFINE_TYPE(QmlStateGroup,StateGroup);
+
+class QmlStateGroupPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlStateGroup)
+public:
+ QmlStateGroupPrivate(QmlStateGroup *p)
+ : nullState(0), states(p), classComplete(true),
+ componentComplete(true), ignoreTrans(false) {}
+
+ QString currentState;
+ QmlState *nullState;
+
+ struct StateList : public QmlConcreteList<QmlState *>
+ {
+ StateList(QmlStateGroup *g)
+ :group(g) {}
+ void append(QmlState *s) {
+ QmlConcreteList<QmlState *>::append(s);
+ if (s) s->setStateGroup(group);
+ }
+ private:
+ QmlStateGroup *group;
+ };
+ StateList states;
+
+ QmlConcreteList<QmlTransition *> transitions;
+ bool classComplete;
+ bool componentComplete;
+ bool ignoreTrans;
+
+ QmlTransition *findTransition(const QString &from, const QString &to);
+ void setCurrentStateInternal(const QString &state, bool = false);
+ void updateAutoState();
+};
+
+QmlStateGroup::QmlStateGroup(QObject *parent)
+ : QObject(*(new QmlStateGroupPrivate(this)), parent)
+{
+}
+
+QmlStateGroup::~QmlStateGroup()
+{
+}
+
+QList<QmlState *> QmlStateGroup::states() const
+{
+ Q_D(const QmlStateGroup);
+ return d->states;
+}
+
+QmlList<QmlState *>* QmlStateGroup::statesProperty()
+{
+ Q_D(QmlStateGroup);
+ return &(d->states);
+}
+
+QmlList<QmlTransition *>* QmlStateGroup::transitionsProperty()
+{
+ Q_D(QmlStateGroup);
+ return &(d->transitions);
+}
+
+QString QmlStateGroup::state() const
+{
+ Q_D(const QmlStateGroup);
+ return d->currentState;
+}
+
+void QmlStateGroup::setState(const QString &state)
+{
+ Q_D(QmlStateGroup);
+ if (d->currentState == state)
+ return;
+
+ d->setCurrentStateInternal(state);
+
+ d->currentState = state;
+ emit stateChanged(d->currentState);
+}
+
+void QmlStateGroup::classBegin()
+{
+ Q_D(QmlStateGroup);
+ d->classComplete = false;
+ d->componentComplete = false;
+}
+
+void QmlStateGroup::classComplete()
+{
+ Q_D(QmlStateGroup);
+ d->classComplete = true;
+}
+
+void QmlStateGroup::updateAutoState()
+{
+ Q_D(QmlStateGroup);
+ d->updateAutoState();
+}
+
+void QmlStateGroupPrivate::updateAutoState()
+{
+ Q_Q(QmlStateGroup);
+ if (!classComplete)
+ return;
+
+ bool revert = false;
+ for (int ii = 0; ii < states.count(); ++ii) {
+ QmlState *state = states.at(ii);
+ if (state->isWhenKnown()) {
+ if (!state->name().isEmpty()) {
+ if (state->when() && state->when()->value().toBool()) {
+ if (stateChangeDebug())
+ qWarning() << "Setting auto state due to:"
+ << state->when()->expression();
+ q->setState(state->name());
+ return;
+ } else if (state->name() == currentState) {
+ revert = true;
+ }
+ }
+ }
+ }
+ if (revert)
+ q->setState(QString());
+}
+
+QmlTransition *QmlStateGroupPrivate::findTransition(const QString &from, const QString &to)
+{
+ QmlTransition *highest = 0;
+ int score = 0;
+ bool reversed = false;
+ bool done = false;
+
+ for (int ii = 0; !done && ii < transitions.count(); ++ii) {
+ QmlTransition *t = transitions.at(ii);
+ for (int ii = 0; ii < 2; ++ii)
+ {
+ if (ii && (!t->reversible() ||
+ (t->fromState() == QLatin1String("*") &&
+ t->toState() == QLatin1String("*"))))
+ break;
+ QStringList fromState;
+ QStringList toState;
+
+ fromState = t->fromState().split(QLatin1Char(','));
+ toState = t->toState().split(QLatin1Char(','));
+ if (ii == 1)
+ qSwap(fromState, toState);
+ int tScore = 0;
+ if (fromState.contains(from))
+ tScore += 2;
+ else if (fromState.contains(QLatin1String("*")))
+ tScore += 1;
+ else
+ continue;
+
+ if (toState.contains(to))
+ tScore += 2;
+ else if (toState.contains(QLatin1String("*")))
+ tScore += 1;
+ else
+ continue;
+
+ if (ii == 1)
+ reversed = true;
+ else
+ reversed = false;
+
+ if (tScore == 4) {
+ highest = t;
+ done = true;
+ break;
+ } else if (tScore > score) {
+ score = tScore;
+ highest = t;
+ }
+ }
+ }
+
+ if (highest)
+ highest->setReversed(reversed);
+
+ return highest;
+}
+
+void QmlStateGroupPrivate::setCurrentStateInternal(const QString &state,
+ bool ignoreTrans)
+{
+ Q_Q(QmlStateGroup);
+ if (!componentComplete)
+ return;
+
+ QmlTransition *transition = (ignoreTrans || ignoreTrans) ? 0 : findTransition(currentState, state);
+ if (stateChangeDebug()) {
+ qWarning() << this << "Changing state. From" << currentState << ". To" << state;
+ if (transition)
+ qWarning() << " using transition" << transition->fromState()
+ << transition->toState();
+ }
+
+ QmlState *oldState = 0;
+ if (!currentState.isEmpty()) {
+ for (int ii = 0; ii < states.count(); ++ii) {
+ if (states.at(ii)->name() == currentState) {
+ oldState = states.at(ii);
+ break;
+ }
+ }
+ }
+
+ currentState = state;
+
+ QmlState *newState = 0;
+ for (int ii = 0; ii < states.count(); ++ii) {
+ if (states.at(ii)->name() == currentState) {
+ newState = states.at(ii);
+ break;
+ }
+ }
+
+ if (oldState == 0 || newState == 0) {
+ if (!nullState) { nullState = new QmlState(q); }
+ if (!oldState) oldState = nullState;
+ if (!newState) newState = nullState;
+ }
+
+ newState->apply(q, transition, oldState);
+}
+
+void QmlStateGroup::componentComplete()
+{
+ Q_D(QmlStateGroup);
+ d->updateAutoState();
+ d->componentComplete = true;
+ if (!d->currentState.isEmpty()) {
+ QString cs = d->currentState;
+ d->currentState = QString();
+ d->setCurrentStateInternal(cs, true);
+ }
+}
+
+QmlState *QmlStateGroup::findState(const QString &name) const
+{
+ Q_D(const QmlStateGroup);
+ for (int i = 0; i < d->states.count(); ++i) {
+ QmlState *state = d->states.at(i);
+ if (state->name() == name)
+ return state;
+ }
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlstategroup.h b/src/declarative/util/qmlstategroup.h
new file mode 100644
index 0000000..55b84eb
--- /dev/null
+++ b/src/declarative/util/qmlstategroup.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTATEGROUP_H
+#define QMLSTATEGROUP_H
+
+#include <qmlstate.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlStateGroupPrivate;
+class QmlStateGroup : public QObject, public QmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QmlParserStatus)
+ Q_DECLARE_PRIVATE(QmlStateGroup);
+
+ Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged);
+ Q_PROPERTY(QmlList<QmlState *>* states READ statesProperty DESIGNABLE false);
+ Q_PROPERTY(QmlList<QmlTransition *>* transitions READ transitionsProperty DESIGNABLE false);
+
+public:
+ QmlStateGroup(QObject * = 0);
+ virtual ~QmlStateGroup();
+
+ QString state() const;
+ void setState(const QString &);
+
+ QmlList<QmlState *>* statesProperty();
+ QList<QmlState *> states() const;
+
+ QmlList<QmlTransition *>* transitionsProperty();
+
+ QmlState *findState(const QString &name) const;
+
+ virtual void classBegin();
+ virtual void classComplete();
+ virtual void componentComplete();
+Q_SIGNALS:
+ void stateChanged(const QString &);
+
+private:
+ friend class QmlState;
+ void updateAutoState();
+};
+QML_DECLARE_TYPE(QmlStateGroup);
+
+#endif // QMLSTATEGROUP_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/util/qmlstateoperations.cpp b/src/declarative/util/qmlstateoperations.cpp
new file mode 100644
index 0000000..01f9cdd
--- /dev/null
+++ b/src/declarative/util/qmlstateoperations.cpp
@@ -0,0 +1,432 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qobject_p.h>
+#include <qml.h>
+#include <QtDeclarative/qmlcontext.h>
+#include "qmlbindablevalue.h"
+#include "qmlstateoperations.h"
+#include <QtCore/qdebug.h>
+#include <QtDeclarative/qmlinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlParentChangePrivate : public QObjectPrivate
+{
+public:
+ QmlParentChangePrivate() : target(0), parent(0) {}
+
+ QObject *target;
+ QObject *parent;
+};
+
+/*!
+ \preliminary
+ \qmlclass ParentChange
+ \brief The ParentChange element allows you to reparent an object in a state.
+*/
+
+QML_DEFINE_TYPE(QmlParentChange,ParentChange);
+QmlParentChange::QmlParentChange(QObject *parent)
+ : QmlStateOperation(*(new QmlParentChangePrivate), parent)
+{
+}
+
+QmlParentChange::~QmlParentChange()
+{
+}
+
+/*!
+ \qmlproperty Object ParentChange::target
+ This property holds the object to be reparented
+*/
+
+QObject *QmlParentChange::object() const
+{
+ Q_D(const QmlParentChange);
+ return d->target;
+}
+void QmlParentChange::setObject(QObject *target)
+{
+ Q_D(QmlParentChange);
+ d->target = target;
+}
+
+/*!
+ \qmlproperty Object ParentChange::parent
+ This property holds the parent for the object in this state
+*/
+
+QObject *QmlParentChange::parent() const
+{
+ Q_D(const QmlParentChange);
+ return d->parent;
+}
+
+void QmlParentChange::setParent(QObject *parent)
+{
+ Q_D(QmlParentChange);
+ d->parent = parent;
+}
+
+QmlStateOperation::ActionList QmlParentChange::actions()
+{
+ Q_D(QmlParentChange);
+ if (!d->target || !d->parent)
+ return ActionList();
+
+ QString propName(QLatin1String("moveToParent"));
+ QmlMetaProperty prop(d->target, propName);
+ if (!prop.isValid()) {
+ qmlInfo(this) << d->target->metaObject()->className()
+ << "has no property named" << propName;
+ return ActionList();
+ }else if (!prop.isWritable()){
+ qmlInfo(this) << d->target->metaObject()->className() << propName
+ << "is not a writable property and cannot be set.";
+ return ActionList();
+ }
+ QVariant cur = prop.read();
+
+ Action a;
+ a.property = prop;
+ a.fromValue = cur;
+ a.toValue = qVariantFromValue(d->parent);
+
+ return ActionList() << a;
+}
+
+class QmlRunScriptPrivate : public QObjectPrivate
+{
+public:
+ QmlRunScriptPrivate() {}
+
+ QString script;
+ QString name;
+};
+
+/*!
+ \qmlclass RunScript QmlRunScript
+ \brief The RunScript element allows you to run a script in a state.
+*/
+QML_DEFINE_TYPE(QmlRunScript,RunScript);
+QmlRunScript::QmlRunScript(QObject *parent)
+: QmlStateOperation(*(new QmlRunScriptPrivate), parent)
+{
+}
+
+QmlRunScript::~QmlRunScript()
+{
+}
+
+/*!
+ \qmlproperty string RunScript::script
+ This property holds the script to run when the state is current.
+*/
+QString QmlRunScript::script() const
+{
+ Q_D(const QmlRunScript);
+ return d->script;
+}
+
+void QmlRunScript::setScript(const QString &s)
+{
+ Q_D(QmlRunScript);
+ d->script = s;
+}
+
+QString QmlRunScript::name() const
+{
+ Q_D(const QmlRunScript);
+ return d->name;
+}
+
+void QmlRunScript::setName(const QString &n)
+{
+ Q_D(QmlRunScript);
+ d->name = n;
+}
+
+void QmlRunScript::execute()
+{
+ Q_D(QmlRunScript);
+ if (!d->script.isEmpty()) {
+ QmlExpression expr(qmlContext(this), d->script, this);
+ expr.setTrackChange(false);
+ expr.value();
+ }
+}
+
+QmlRunScript::ActionList QmlRunScript::actions()
+{
+ ActionList rv;
+ Action a;
+ a.event = this;
+ rv << a;
+ return rv;
+}
+
+/*!
+ \qmlclass SetProperty QmlSetProperty
+ \brief The SetProperty element describes a new property value or binding for a state.
+
+ The code below changes the position of the Rect depending upon
+ the current state:
+
+ \code
+ Rect {
+ id: myrect
+ width: 50
+ height: 50
+ color: "red"
+ }
+
+ states: [
+ State {
+ name: "Position1"
+ SetProperty {
+ target: myrect
+ property: "x"
+ value: 150
+ }
+ SetProperty {
+ target: myrect
+ property: "y"
+ value: 50
+ }
+ },
+ State {
+ name: "Position2"
+ SetProperty {
+ target: myrect
+ property: "y"
+ value: 200
+ }
+ }
+ ]
+ \endcode
+
+ \sa SetProperties
+*/
+
+/*!
+ \internal
+ \class QmlSetProperty
+ \brief The QmlSetProperty class describes a new property value or binding for a state.
+
+ \ingroup group_states
+
+ \sa QmlSetProperties
+*/
+
+class QmlSetPropertyPrivate : public QObjectPrivate
+{
+public:
+ QmlSetPropertyPrivate() : obj(0) {}
+
+ QObject *obj;
+ QString prop;
+ QVariant value;
+ QString binding;
+};
+
+QML_DEFINE_TYPE(QmlSetProperty,SetProperty);
+
+QmlSetProperty::QmlSetProperty(QObject *parent)
+ : QmlStateOperation(*(new QmlSetPropertyPrivate), parent)
+{
+}
+
+QmlSetProperty::~QmlSetProperty()
+{
+}
+
+/*!
+ \qmlproperty Object SetProperty::target
+ This property holds the object the property to change belongs to
+*/
+
+/*!
+ \property QmlSetProperty::target
+ \brief the object the property to change belongs to
+*/
+QObject *QmlSetProperty::object()
+{
+ Q_D(QmlSetProperty);
+ return d->obj;
+}
+
+void QmlSetProperty::setObject(QObject *o)
+{
+ Q_D(QmlSetProperty);
+ d->obj = o;
+}
+
+/*!
+ \qmlproperty string SetProperty::property
+ This property holds the name of the property to change
+*/
+
+/*!
+ \property QmlSetProperty::property
+ \brief the name of the property to change
+*/
+QString QmlSetProperty::property() const
+{
+ Q_D(const QmlSetProperty);
+ return d->prop;
+}
+
+void QmlSetProperty::setProperty(const QString &p)
+{
+ Q_D(QmlSetProperty);
+ d->prop = p;
+}
+
+/*!
+ \qmlproperty variant SetProperty::value
+ This property holds the value to assign to the property
+
+ You should set either a \c value or a \c binding, but not both.
+*/
+
+/*!
+ \property QmlSetProperty::value
+ \brief the value to assign to the property
+
+ You should set either a value or a binding, not both.
+*/
+QVariant QmlSetProperty::value() const
+{
+ Q_D(const QmlSetProperty);
+ return d->value;
+}
+
+void QmlSetProperty::setValue(const QVariant &v)
+{
+ Q_D(QmlSetProperty);
+ d->value = v;
+}
+
+/*!
+ \qmlproperty string SetProperty::binding
+ This property holds the binding to assign to the property
+
+ You should set either a \c value or a \c binding, but not both.
+*/
+
+/*!
+ \property QmlSetProperty::binding
+ \brief the binding to assign to the property
+
+ You should set either a value or a binding, not both.
+*/
+QString QmlSetProperty::binding() const
+{
+ Q_D(const QmlSetProperty);
+ return d->binding;
+}
+
+void QmlSetProperty::setBinding(const QString &binding)
+{
+ Q_D(QmlSetProperty);
+ d->binding = binding;
+}
+
+QmlSetProperty::ActionList QmlSetProperty::actions()
+{
+ Q_D(QmlSetProperty);
+ if (!d->obj)
+ return ActionList();
+
+ QObject *obj = d->obj;
+ QString propName = d->prop;
+
+ if (d->prop.contains(QLatin1Char('.'))) { //handle dot properties
+ QStringList str = d->prop.split(QLatin1Char('.'));
+ for (int ii = 0; ii < str.count()-1; ++ii) {
+ const QString &s = str.at(ii);
+ QmlMetaProperty prop(obj, s);
+ if (!prop.isValid()) {
+ qmlInfo(this) << obj->metaObject()->className()
+ << "has no property named" << s;
+ return ActionList();
+ }
+ QVariant v = prop.read();
+ obj = QmlMetaType::toQObject(v);
+ if (!obj) {
+ qmlInfo(this) << "Unable to coerce value property"
+ << s << "into a QObject";
+ return ActionList();
+ }
+ }
+ propName = str.last();
+ }
+
+ QmlMetaProperty prop(obj, propName);
+ if (!prop.isValid()) {
+ qmlInfo(this) << obj->metaObject()->className()
+ << "has no property named" << propName;
+ return ActionList();
+ }else if (!prop.isWritable()){
+ qmlInfo(this) << obj->metaObject()->className() << propName
+ << "is not a writable property and cannot be set.";
+ return ActionList();
+ }
+ QVariant cur = prop.read();
+
+ Action a;
+ a.property = prop;
+ a.fromValue = cur;
+ a.toValue = d->value;
+ if (!d->binding.isEmpty()) {
+ QmlBindableValue *bv = prop.binding();
+ if (bv) {
+ a.fromBinding = bv->expression();
+ a.bv = bv;
+ }
+ }
+ a.toBinding = d->binding;
+
+ return ActionList() << a;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlstateoperations.h b/src/declarative/util/qmlstateoperations.h
new file mode 100644
index 0000000..8ecdcd2
--- /dev/null
+++ b/src/declarative/util/qmlstateoperations.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTATEOPERATIONS_H
+#define QMLSTATEOPERATIONS_H
+
+#include <qmlstate.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlParentChangePrivate;
+class Q_DECLARATIVE_EXPORT QmlParentChange : public QmlStateOperation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlParentChange);
+
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(QObject *parent READ parent WRITE setParent)
+public:
+ QmlParentChange(QObject *parent=0);
+ ~QmlParentChange();
+
+ QObject *object() const;
+ void setObject(QObject *);
+
+ QObject *parent() const;
+ void setParent(QObject *);
+
+ virtual ActionList actions();
+};
+QML_DECLARE_TYPE(QmlParentChange);
+
+class QmlRunScriptPrivate;
+class Q_DECLARATIVE_EXPORT QmlRunScript : public QmlStateOperation, public ActionEvent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlRunScript)
+
+ Q_PROPERTY(QString script READ script WRITE setScript);
+ Q_PROPERTY(QString name READ name WRITE setName);
+
+public:
+ QmlRunScript(QObject *parent=0);
+ ~QmlRunScript();
+
+ virtual ActionList actions();
+
+ QString script() const;
+ void setScript(const QString &);
+
+ virtual QString name() const;
+ void setName(const QString &);
+
+ virtual void execute();
+};
+QML_DECLARE_TYPE(QmlRunScript);
+
+class QmlSetPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlSetProperty : public QmlStateOperation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlSetProperty);
+
+ Q_PROPERTY(QObject *target READ object WRITE setObject);
+ Q_PROPERTY(QString property READ property WRITE setProperty);
+ Q_PROPERTY(QVariant value READ value WRITE setValue);
+ Q_PROPERTY(QString binding READ binding WRITE setBinding);
+
+public:
+ QmlSetProperty(QObject *parent=0);
+ ~QmlSetProperty();
+
+ QObject *object();
+ void setObject(QObject *);
+ QString property() const;
+ void setProperty(const QString &);
+ QVariant value() const;
+ void setValue(const QVariant &);
+ QString binding() const;
+ void setBinding(const QString&);
+
+ virtual ActionList actions();
+};
+QML_DECLARE_TYPE(QmlSetProperty);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLSTATEOPERATIONS_H
diff --git a/src/declarative/util/qmltransition.cpp b/src/declarative/util/qmltransition.cpp
new file mode 100644
index 0000000..26ed8b1
--- /dev/null
+++ b/src/declarative/util/qmltransition.cpp
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlstate.h"
+#include "qmlstategroup.h"
+#include "qmlstate_p.h"
+#include "qmlbindablevalue.h"
+#include "qmlstateoperations.h"
+#include "qmlanimation.h"
+#include "qmlanimation_p.h"
+#include <QParallelAnimationGroup>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass Transition QmlTransition
+ \brief The Transition element defines animated transitions that occur on state changes.
+
+ \sa {states-transitions}{States and Transitions}
+*/
+
+/*!
+ \internal
+ \class QmlTransition
+ \brief The QmlTransition class allows you to define animated transitions that occur on state changes.
+
+ \ingroup group_states
+*/
+
+//ParallelAnimationWrapperallows us to do a "callback" when the animation finishes, rather than connecting
+//and disconnecting signals and slots frequently
+class ParallelAnimationWrapper : public QParallelAnimationGroup
+{
+ Q_OBJECT
+public:
+ ParallelAnimationWrapper(QObject *parent) : QParallelAnimationGroup(parent) {}
+ QmlTransitionPrivate *trans;
+protected:
+ virtual void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+};
+
+class QmlTransitionPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlTransition)
+public:
+ QmlTransitionPrivate() : fromState(QLatin1String("*")), toState(QLatin1String("*"))
+ , reversed(false), reversible(false), group(0), endState(0)
+ {
+ operations.parent = this;
+ }
+
+ QString fromState;
+ QString toState;
+ bool reversed;
+ bool reversible;
+ ParallelAnimationWrapper *group;
+ QmlState *endState;
+
+ void init()
+ {
+ Q_Q(QmlTransition);
+ group = new ParallelAnimationWrapper(q);
+ group->trans = this;
+ }
+
+ void complete()
+ {
+ endState->d_func()->complete();
+ }
+
+ class AnimationList : public QmlConcreteList<QmlAbstractAnimation *>
+ {
+ public:
+ AnimationList() : parent(0) {}
+ virtual void append(QmlAbstractAnimation *a);
+ virtual void clear() { QmlConcreteList<QmlAbstractAnimation *>::clear(); } //XXX
+
+ QmlTransitionPrivate *parent;
+ };
+ AnimationList operations;
+};
+
+void QmlTransitionPrivate::AnimationList::append(QmlAbstractAnimation *a)
+{
+ QmlConcreteList<QmlAbstractAnimation *>::append(a);
+ parent->group->addAnimation(a->qtAnimation());
+}
+
+void ParallelAnimationWrapper::updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState)
+{
+ QParallelAnimationGroup::updateState(oldState, newState);
+ //XXX not 100% guaranteed to be at end (if there are many zero duration animations at the end)?
+ if (newState == Stopped && currentTime() == duration())
+ {
+ trans->complete();
+ }
+}
+
+
+QML_DEFINE_TYPE(QmlTransition,Transition);
+QmlTransition::QmlTransition(QObject *parent)
+ : QObject(*(new QmlTransitionPrivate), parent)
+{
+ Q_D(QmlTransition);
+ d->init();
+}
+
+QmlTransition::~QmlTransition()
+{
+}
+
+void QmlTransition::stop()
+{
+ Q_D(QmlTransition);
+ d->group->stop();
+}
+
+void QmlTransition::setReversed(bool r)
+{
+ Q_D(QmlTransition);
+ d->reversed = r;
+}
+
+void QmlTransition::prepare(QmlStateOperation::ActionList &actions,
+ QList<QmlMetaProperty> &after,
+ QmlState *endState)
+{
+ Q_D(QmlTransition);
+
+ if (d->reversed) {
+ for (int ii = d->operations.count() - 1; ii >= 0; --ii) {
+ d->operations.at(ii)->transition(actions, after, QmlAbstractAnimation::Backward);
+ }
+ } else {
+ for (int ii = 0; ii < d->operations.count(); ++ii) {
+ d->operations.at(ii)->transition(actions, after, QmlAbstractAnimation::Forward);
+ }
+ }
+
+ d->endState = endState;
+ d->group->start();
+}
+
+/*!
+ \qmlproperty string Transition::fromState
+ \qmlproperty string Transition::toState
+ These properties are selectors indicating which state changes should trigger the transition.
+
+ fromState is used in conjunction with toState to determine when a transition should
+ be applied. By default fromState and toState are both "*" (any state). In the following example,
+ the transition is applied when changing from state1 to state2.
+ \code
+ Transition {
+ fromState: "state1"
+ toState: "state2"
+ ...
+ }
+ \endcode
+*/
+
+/*!
+ \property QmlTransition::fromState
+ \brief a selector indicating which states, when left, should trigger the transition.
+
+ fromState is used in conjunction with toState to determine when a transition should
+ be applied. The default value is "*" (any state).
+*/
+QString QmlTransition::fromState() const
+{
+ Q_D(const QmlTransition);
+ return d->fromState;
+}
+
+void QmlTransition::setFromState(const QString &f)
+{
+ Q_D(QmlTransition);
+ d->fromState = f;
+}
+
+/*!
+ \qmlproperty bool Transition::reversible
+ This property holds whether the transition should be automatically reversed when the conditions that triggered this transition are reversed.
+
+ The default value is false.
+*/
+
+
+/*!
+ \property QmlTransition::reversible
+ \brief whether the transition should be automatically reversed when the conditions that triggered this transition are reversed.
+
+ The default value is false.
+*/
+bool QmlTransition::reversible() const
+{
+ Q_D(const QmlTransition);
+ return d->reversible;
+}
+
+void QmlTransition::setReversible(bool r)
+{
+ Q_D(QmlTransition);
+ d->reversible = r;
+}
+
+/*!
+ \property QmlTransition::toState
+ \brief a selector indicating which states, when entered, should trigger the transition.
+
+ toState is used in conjunction with fromState to determine when a transition should
+ be applied. The default value is "*" (any state).
+*/
+QString QmlTransition::toState() const
+{
+ Q_D(const QmlTransition);
+ return d->toState;
+}
+
+void QmlTransition::setToState(const QString &t)
+{
+ Q_D(QmlTransition);
+ d->toState = t;
+}
+
+/*!
+ \qmlproperty list<Animation> Transition::operations
+ This property holds a list of the animations to be run for this transition.
+
+ The top-level animations in operations are run in parallel.
+ To run them sequentially, you can create a single SequentialAnimation
+ which contains all the animations, and assign that to operations.
+ \default
+*/
+
+/*!
+ \property QmlTransition::operations
+ \brief a list of the transition animations to be run.
+*/
+QmlList<QmlAbstractAnimation *>* QmlTransition::operations()
+{
+ Q_D(QmlTransition);
+ return &d->operations;
+}
+
+QT_END_NAMESPACE
+
+#include "qmltransition.moc"
diff --git a/src/declarative/util/qmltransition.h b/src/declarative/util/qmltransition.h
new file mode 100644
index 0000000..0b7ea14
--- /dev/null
+++ b/src/declarative/util/qmltransition.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTRANSITION_H
+#define QMLTRANSITION_H
+
+#include <QtCore/qobject.h>
+#include <qfxglobal.h>
+#include <qmlstate.h>
+#include <qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlAbstractAnimation;
+class QmlTransitionPrivate;
+class Q_DECLARATIVE_EXPORT QmlTransition : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlTransition)
+
+ Q_PROPERTY(QString fromState READ fromState WRITE setFromState)
+ Q_PROPERTY(QString toState READ toState WRITE setToState)
+ Q_PROPERTY(bool reversible READ reversible WRITE setReversible)
+ Q_PROPERTY(QmlList<QmlAbstractAnimation *>* operations READ operations)
+ Q_CLASSINFO("DefaultProperty", "operations")
+
+public:
+ QmlTransition(QObject *parent=0);
+ ~QmlTransition();
+
+ QString fromState() const;
+ void setFromState(const QString &);
+
+ QString toState() const;
+ void setToState(const QString &);
+
+ bool reversible() const;
+ void setReversible(bool);
+
+ QmlList<QmlAbstractAnimation *>* operations();
+
+ void prepare(QmlStateOperation::ActionList &actions,
+ QList<QmlMetaProperty> &after,
+ QmlState *endState);
+
+ void setReversed(bool r);
+ void stop();
+};
+QML_DECLARE_TYPE(QmlTransition);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLTRANSITION_H
diff --git a/src/declarative/util/qperformancelog.cpp b/src/declarative/util/qperformancelog.cpp
new file mode 100644
index 0000000..8065f9d
--- /dev/null
+++ b/src/declarative/util/qperformancelog.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qperformancelog.h"
+#include <QHash>
+#include <QDebug>
+
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+
+struct QPerformanceLogData
+{
+ struct Log
+ {
+ Log()
+ : logDescription(0), maxId(-1) {}
+
+ QHash<int, const char *> descriptions;
+ const char *logDescription;
+ int maxId;
+ };
+
+ typedef QHash<QPerformanceLog::LogData *, Log> Logs;
+ Logs logs;
+};
+Q_GLOBAL_STATIC(QPerformanceLogData, performanceLogData);
+
+QPerformanceLog::LogData::LogData(const char *desc)
+: sumTime(0), data(0)
+{
+ QPerformanceLogData *logData = performanceLogData();
+
+ QPerformanceLogData::Log log;
+ log.logDescription = desc;
+ logData->logs.insert(this, log);
+
+ timer.start();
+}
+
+QPerformanceLog::LogMetric::LogMetric(LogData *l, int id, const char *desc)
+{
+ if (id < 0)
+ qFatal("QPerformanceLog: Invalid log id %d ('%s')", id, desc);
+
+ QPerformanceLogData *logData = performanceLogData();
+
+ QPerformanceLogData::Logs::Iterator logIter = logData->logs.find(l);
+ if (logIter == logData->logs.end())
+ qFatal("QPerformanceLog: Unable to locate log for metric '%s'", desc);
+ QPerformanceLogData::Log &log = *logIter;
+ if (log.descriptions.contains(id))
+ qFatal("QPerformanceLog: Duplicate log metric %d ('%s')", id, desc);
+ log.descriptions.insert(id, desc);
+
+ if (log.maxId < id) {
+ log.maxId = id;
+ if (l->data) delete [] l->data;
+ l->data = new unsigned int[2 * (log.maxId + 1)];
+ ::memset(l->data, 0, 2 * (log.maxId + 1) * sizeof(unsigned int));
+ }
+}
+
+static void QPerformanceLog_clear(QPerformanceLog::LogData *l, const QPerformanceLogData::Log *pl)
+{
+ ::memset(l->data, 0, 2 * (pl->maxId + 1) * sizeof(unsigned int));
+}
+
+static void QPerformanceLog_displayData(const QPerformanceLog::LogData *l, const QPerformanceLogData::Log *pl)
+{
+ qWarning() << pl->logDescription << "performance data";
+ unsigned int total = 0;
+ for (QHash<int, const char *>::ConstIterator iter = pl->descriptions.begin();
+ iter != pl->descriptions.end();
+ ++iter) {
+
+ int id = iter.key();
+ unsigned int ms = l->data[id * 2];
+ total += ms;
+ unsigned int inst = l->data[id * 2 + 1];
+ float pi = float(ms) / float(inst);
+ qWarning().nospace() << " " << *iter << ": " << ms << " ms over "
+ << inst << " instances (" << pi << " ms/instance)";
+ }
+ qWarning().nospace() << " TOTAL: " << total;
+}
+
+void QPerformanceLog::displayData()
+{
+ QPerformanceLogData *logData = performanceLogData();
+
+ for (QPerformanceLogData::Logs::ConstIterator iter = logData->logs.begin();
+ iter != logData->logs.end();
+ ++iter) {
+ QPerformanceLog_displayData(iter.key(), &(*iter));
+ }
+}
+
+void QPerformanceLog::clear()
+{
+ QPerformanceLogData *logData = performanceLogData();
+
+ for (QPerformanceLogData::Logs::ConstIterator iter = logData->logs.begin();
+ iter != logData->logs.end();
+ ++iter) {
+ QPerformanceLog_clear(iter.key(), &(*iter));
+ }
+}
+
+void QPerformanceLog::displayData(LogData *l)
+{
+ QPerformanceLogData *logData = performanceLogData();
+ QPerformanceLogData::Logs::ConstIterator iter = logData->logs.find(l);
+ if (iter == logData->logs.end())
+ qFatal("QPerformanceLog: Internal corruption - unable to locate log");
+
+ QPerformanceLog_displayData(iter.key(), &(*iter));
+}
+
+void QPerformanceLog::clear(LogData *l)
+{
+ QPerformanceLogData *logData = performanceLogData();
+ QPerformanceLogData::Logs::ConstIterator iter = logData->logs.find(l);
+ if (iter == logData->logs.end())
+ qFatal("QPerformanceLog: Internal corruption - unable to locate log");
+
+ QPerformanceLog_clear(iter.key(), &(*iter));
+}
+
+#else // Q_ENABLE_PERFORMANCE_LOG
+
+void QPerformanceLog::displayData()
+{
+}
+
+void QPerformanceLog::clear()
+{
+}
+
+#endif // Q_ENABLE_PERFORMANCE_LOG
diff --git a/src/declarative/util/qperformancelog.h b/src/declarative/util/qperformancelog.h
new file mode 100644
index 0000000..9d19bbd
--- /dev/null
+++ b/src/declarative/util/qperformancelog.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPERFORMANCELOG_H
+#define QPERFORMANCELOG_H
+
+#include <QtCore/qdatetime.h>
+namespace QPerformanceLog
+{
+ Q_DECLARATIVE_EXPORT void displayData();
+ Q_DECLARATIVE_EXPORT void clear();
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ struct LogData {
+ LogData(const char *);
+ QTime timer;
+ int sumTime;
+ unsigned int *data;
+ };
+
+ struct LogMetric {
+ LogMetric(LogData *, int, const char *);
+ };
+
+ // Internal
+ void displayData(LogData *);
+ void clear(LogData *);
+#endif
+};
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+
+#define Q_DECLARE_PERFORMANCE_METRIC(name) \
+ enum { name = ValueChoice<0, ValueTracker<0, __LINE__>::value, __LINE__>::value }; \
+ template<int L> \
+ struct ValueTracker<name, L> \
+ { \
+ enum { value = name }; \
+ }; \
+ extern QPerformanceLog::LogMetric metric ## name;
+
+#define Q_DECLARE_PERFORMANCE_LOG(name) \
+ namespace name { \
+ extern QPerformanceLog::LogData log; \
+ inline void displayData() { QPerformanceLog::displayData(&log); } \
+ inline void clear() { QPerformanceLog::clear(&log); } \
+ } \
+ template<int N> \
+ class name ## Timer { \
+ public: \
+ name ## Timer() { \
+ lastSum = name::log.sumTime + name::log.timer.restart(); \
+ name::log.sumTime = 0; \
+ } \
+ ~ name ## Timer() { \
+ name::log.data[2 * N] += name::log.sumTime + name::log.timer.restart(); \
+ ++name::log.data[2 * N + 1]; \
+ name::log.sumTime = lastSum; \
+ } \
+ private: \
+ int lastSum; \
+ }; \
+ namespace name { \
+ template<int N, int L> \
+ struct ValueTracker \
+ { \
+ enum { value = -1 }; \
+ }; \
+ template<int DefNextValue, int NextValue, int L> \
+ struct ValueChoice \
+ { \
+ enum { value = ValueChoice<DefNextValue + 1, ValueTracker<DefNextValue + 1, L>::value, L>::value }; \
+ }; \
+ template<int DefNextValue, int L> \
+ struct ValueChoice<DefNextValue, -1, L> \
+ { \
+ enum { value = DefNextValue }; \
+ }; \
+ } \
+ namespace name
+
+#define Q_DEFINE_PERFORMANCE_LOG(name, desc) \
+ QPerformanceLog::LogData name::log(desc); \
+ namespace name
+
+#define Q_DEFINE_PERFORMANCE_METRIC(name, desc) \
+ QPerformanceLog::LogMetric metrix ## name(&log, name, desc);
+
+#else // Q_ENABLE_PERFORMANCE_LOG
+
+#define Q_DECLARE_PERFORMANCE_METRIC(name) \
+ enum { name = ValueChoice<0, ValueTracker<0, __LINE__>::value, __LINE__>::value }; \
+ template<int L> \
+ struct ValueTracker<name, L> \
+ { \
+ enum { value = name }; \
+ }; \
+
+#define Q_DECLARE_PERFORMANCE_LOG(name) \
+ namespace name { \
+ inline void displayData() { }; \
+ inline void clear() { }; \
+ } \
+ template<int N> \
+ class name ## Timer { \
+ public: \
+ name ## Timer() { \
+ } \
+ ~ name ## Timer() { \
+ } \
+ }; \
+ namespace name { \
+ template<int N, int L> \
+ struct ValueTracker \
+ { \
+ enum { value = -1 }; \
+ }; \
+ template<int DefNextValue, int NextValue, int L> \
+ struct ValueChoice \
+ { \
+ enum { value = ValueChoice<DefNextValue + 1, ValueTracker<DefNextValue + 1, L>::value, L>::value }; \
+ }; \
+ template<int DefNextValue, int L> \
+ struct ValueChoice<DefNextValue, -1, L> \
+ { \
+ enum { value = DefNextValue }; \
+ }; \
+ } \
+ namespace name
+
+#define Q_DEFINE_PERFORMANCE_LOG(name, desc) \
+ namespace name
+
+#define Q_DEFINE_PERFORMANCE_METRIC(name, desc)
+
+#endif // Q_ENABLE_PERFORMANCE_LOG
+
+#endif // QPERFORMANCELOG_H
diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri
new file mode 100644
index 0000000..030a44e
--- /dev/null
+++ b/src/declarative/util/util.pri
@@ -0,0 +1,49 @@
+SOURCES += \
+ util/qfxview.cpp \
+ util/qfxperf.cpp \
+ util/qperformancelog.cpp \
+ util/qmlconnection.cpp \
+ util/qmlpackage.cpp \
+ util/qmlscript.cpp \
+ util/qmlanimation.cpp \
+ util/qmlbehaviour.cpp \
+ util/qmlfont.cpp \
+ util/qmlfollow.cpp \
+ util/qmlstate.cpp\
+ util/qmlstateoperations.cpp \
+ util/qmlsetproperties.cpp \
+ util/qmlstategroup.cpp \
+ util/qmltransition.cpp \
+ util/qbindablemap.cpp \
+ util/qmldatetimeformatter.cpp \
+ util/qmllistmodel.cpp\
+ util/qmllistaccessor.cpp \
+ util/qmlopenmetaobject.cpp \
+ util/qmlbind.cpp
+
+HEADERS += \
+ util/qfxview.h \
+ util/qfxperf.h \
+ util/qfxglobal.h \
+ util/qperformancelog.h \
+ util/qmlconnection.h \
+ util/qmlpackage.h \
+ util/qmlscript.h \
+ util/qmlanimation.h \
+ util/qmlanimation_p.h \
+ util/qmlbehaviour.h \
+ util/qmlfont.h \
+ util/qmlfollow.h \
+ util/qmlstate.h\
+ util/qmlstateoperations.h \
+ util/qmlsetproperties.h \
+ util/qmlstate_p.h\
+ util/qmlstategroup.h \
+ util/qmltransition.h \
+ util/qbindablemap.h \
+ util/qmldatetimeformatter.h \
+ util/qmllistmodel.h\
+ util/qmllistaccessor.h \
+ util/qmlopenmetaobject.h \
+ util/qmlnullablevalue_p.h \
+ util/qmlbind.h
diff --git a/src/declarative/widgets/graphicslayouts.cpp b/src/declarative/widgets/graphicslayouts.cpp
new file mode 100644
index 0000000..d6c4ac2
--- /dev/null
+++ b/src/declarative/widgets/graphicslayouts.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "graphicslayouts.h"
+#include <QtGui/qgraphicswidget.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_INTERFACE(QGraphicsLayoutItem);
+QML_DEFINE_INTERFACE(QGraphicsLayout);
+
+class LinearLayoutAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int stretchFactor READ stretchFactor WRITE setStretchFactor NOTIFY stretchChanged)
+ Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged)
+public:
+ LinearLayoutAttached(QObject *parent)
+ : QObject(parent), _stretch(1), _alignment(Qt::AlignCenter)
+ {
+ }
+
+ int stretchFactor() const { return _stretch; }
+ void setStretchFactor(int f)
+ {
+ if (_stretch == f)
+ return;
+
+ _stretch = f;
+ emit stretchChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _stretch);
+ }
+
+ Qt::Alignment alignment() const { return _alignment; }
+ void setAlignment(Qt::Alignment a)
+ {
+ if (_alignment == a)
+ return;
+
+ _alignment = a;
+ emit alignmentChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _alignment);
+ }
+
+Q_SIGNALS:
+ void stretchChanged(QGraphicsLayoutItem*,int);
+ void alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment);
+
+private:
+ int _stretch;
+ Qt::Alignment _alignment;
+};
+
+QML_DEFINE_TYPE(QGraphicsLinearLayoutStretchItemObject,QGraphicsLinearLayoutStretchItem);
+
+QGraphicsLinearLayoutStretchItemObject::QGraphicsLinearLayoutStretchItemObject(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QSizeF QGraphicsLinearLayoutStretchItemObject::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(which);
+ Q_UNUSED(constraint);
+ return QSizeF();
+}
+
+QML_DEFINE_TYPE(QGraphicsLinearLayoutObject,QGraphicsLinearLayout);
+
+QGraphicsLinearLayoutObject::QGraphicsLinearLayoutObject(QObject *parent)
+: QObject(parent), _children(this)
+{
+}
+
+QGraphicsLinearLayoutObject::~QGraphicsLinearLayoutObject()
+{
+}
+
+void QGraphicsLinearLayoutObject::insertLayoutItem(int index, QGraphicsLayoutItem *item)
+{
+ insertItem(index, item);
+
+ //connect attached properties
+ if (QObject *obj = attachedProperties.value(item)) {
+ setStretchFactor(item, static_cast<LinearLayoutAttached *>(obj)->stretchFactor());
+ setAlignment(item, static_cast<LinearLayoutAttached *>(obj)->alignment());
+ QObject::connect(obj, SIGNAL(stretchChanged(QGraphicsLayoutItem*,int)),
+ this, SLOT(updateStretch(QGraphicsLayoutItem*,int)));
+ QObject::connect(obj, SIGNAL(alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment)),
+ this, SLOT(updateAlignment(QGraphicsLayoutItem*,Qt::Alignment)));
+ //XXX need to disconnect when widget is removed?
+ }
+}
+
+//XXX is there a better way to do this?
+void QGraphicsLinearLayoutObject::clearChildren()
+{
+ for (int i = 0; i < count(); ++i)
+ removeAt(i);
+}
+
+void QGraphicsLinearLayoutObject::updateStretch(QGraphicsLayoutItem *item, int stretch)
+{
+ QGraphicsLinearLayout::setStretchFactor(item, stretch);
+}
+
+void QGraphicsLinearLayoutObject::updateAlignment(QGraphicsLayoutItem *item, Qt::Alignment alignment)
+{
+ QGraphicsLinearLayout::setAlignment(item, alignment);
+}
+
+QHash<QGraphicsLayoutItem*, QObject*> QGraphicsLinearLayoutObject::attachedProperties;
+QObject *QGraphicsLinearLayoutObject::qmlAttachedProperties(QObject *obj)
+{
+ // ### This is not allowed - you must attach to any object
+ if (!qobject_cast<QGraphicsLayoutItem*>(obj))
+ return 0;
+ LinearLayoutAttached *rv = new LinearLayoutAttached(obj);
+ /*if (QGraphicsLinearLayoutObject *lo = qobject_cast<QGraphicsLinearLayoutObject*>(obj->parent()))
+ QObject::connect(rv, SIGNAL(stretchChanged(QGraphicsLayoutItem*,int)),
+ lo, SLOT(updateStretch(QGraphicsLayoutItem*,int)));
+ QObject::connect(rv, SIGNAL(alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment)),
+ lo, SLOT(updateAlignment(QGraphicsLayoutItem*,Qt::Alignment)));*/
+ attachedProperties.insert(qobject_cast<QGraphicsLayoutItem*>(obj), rv);
+ return rv;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// QGraphicsGridLayout-related classes
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+class GridLayoutAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int row READ row WRITE setRow)
+ Q_PROPERTY(int column READ column WRITE setColumn)
+ Q_PROPERTY(int rowSpan READ rowSpan WRITE setRowSpan)
+ Q_PROPERTY(int columnSpan READ columnSpan WRITE setColumnSpan)
+ Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment)
+public:
+ GridLayoutAttached(QObject *parent)
+ : QObject(parent), _row(-1), _column(-1), _rowspan(1), _colspan(1), _alignment(-1)
+ {
+ }
+
+ int row() const { return _row; }
+ void setRow(int r)
+ {
+ if (_row == r)
+ return;
+
+ _row = r;
+ //emit rowChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _row);
+ }
+
+ int column() const { return _column; }
+ void setColumn(int c)
+ {
+ if (_column == c)
+ return;
+
+ _column = c;
+ //emit columnChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _column);
+ }
+
+ int rowSpan() const { return _rowspan; }
+ void setRowSpan(int rs)
+ {
+ if (_rowspan == rs)
+ return;
+
+ _rowspan = rs;
+ //emit rowSpanChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _rowSpan);
+ }
+
+ int columnSpan() const { return _colspan; }
+ void setColumnSpan(int cs)
+ {
+ if (_colspan == cs)
+ return;
+
+ _colspan = cs;
+ //emit columnSpanChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _columnSpan);
+ }
+
+ Qt::Alignment alignment() const { return _alignment; }
+ void setAlignment(Qt::Alignment a)
+ {
+ if (_alignment == a)
+ return;
+
+ _alignment = a;
+ //emit alignmentChanged(reinterpret_cast<QGraphicsLayoutItem*>(parent()), _alignment);
+ }
+
+Q_SIGNALS:
+ //void rowChanged(QGraphicsLayoutItem*,int);
+ //void columnSpanChanged(QGraphicsLayoutItem*,int);
+ //void rowSpanChanged(QGraphicsLayoutItem*,int);
+ //void columnChanged(QGraphicsLayoutItem*,int);
+ //void alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment);
+
+private:
+ int _row;
+ int _column;
+ int _rowspan;
+ int _colspan;
+ Qt::Alignment _alignment;
+};
+
+QML_DEFINE_TYPE(QGraphicsGridLayoutObject,QGraphicsGridLayout);
+
+
+QGraphicsGridLayoutObject::QGraphicsGridLayoutObject(QObject *parent)
+: QObject(parent), _children(this)
+{
+}
+
+QGraphicsGridLayoutObject::~QGraphicsGridLayoutObject()
+{
+}
+
+void QGraphicsGridLayoutObject::addWidget(QGraphicsWidget *wid)
+{
+ //use attached properties
+ if (QObject *obj = attachedProperties.value(qobject_cast<QGraphicsLayoutItem*>(wid))) {
+ int row = static_cast<GridLayoutAttached *>(obj)->row();
+ int column = static_cast<GridLayoutAttached *>(obj)->column();
+ int rowSpan = static_cast<GridLayoutAttached *>(obj)->rowSpan();
+ int columnSpan = static_cast<GridLayoutAttached *>(obj)->columnSpan();
+ if (row == -1 || column == -1) {
+ qWarning() << "Must set row and column for an item in a grid layout";
+ return;
+ }
+ addItem(wid, row, column, rowSpan, columnSpan);
+ }
+}
+
+void QGraphicsGridLayoutObject::addLayoutItem(QGraphicsLayoutItem *item)
+{
+ //use attached properties
+ if (QObject *obj = attachedProperties.value(item)) {
+ int row = static_cast<GridLayoutAttached *>(obj)->row();
+ int column = static_cast<GridLayoutAttached *>(obj)->column();
+ int rowSpan = static_cast<GridLayoutAttached *>(obj)->rowSpan();
+ int columnSpan = static_cast<GridLayoutAttached *>(obj)->columnSpan();
+ Qt::Alignment alignment = static_cast<GridLayoutAttached *>(obj)->alignment();
+ if (row == -1 || column == -1) {
+ qWarning() << "Must set row and column for an item in a grid layout";
+ return;
+ }
+ addItem(item, row, column, rowSpan, columnSpan);
+ if (alignment != -1)
+ setAlignment(item,alignment);
+ }
+}
+
+//XXX is there a better way to do this?
+void QGraphicsGridLayoutObject::clearChildren()
+{
+ for (int i = 0; i < count(); ++i)
+ removeAt(i);
+}
+
+qreal QGraphicsGridLayoutObject::spacing() const
+{
+ if (verticalSpacing() == horizontalSpacing())
+ return verticalSpacing();
+ return -1; //XXX
+}
+
+QHash<QGraphicsLayoutItem*, QObject*> QGraphicsGridLayoutObject::attachedProperties;
+QObject *QGraphicsGridLayoutObject::qmlAttachedProperties(QObject *obj)
+{
+ // ### This is not allowed - you must attach to any object
+ if (!qobject_cast<QGraphicsLayoutItem*>(obj))
+ return 0;
+ GridLayoutAttached *rv = new GridLayoutAttached(obj);
+ attachedProperties.insert(qobject_cast<QGraphicsLayoutItem*>(obj), rv);
+ return rv;
+}
+
+QT_END_NAMESPACE
+
+#include "graphicslayouts.moc"
diff --git a/src/declarative/widgets/graphicslayouts.h b/src/declarative/widgets/graphicslayouts.h
new file mode 100644
index 0000000..beb4b65
--- /dev/null
+++ b/src/declarative/widgets/graphicslayouts.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRAPHICSLAYOUTS_H
+#define GRAPHICSLAYOUTS_H
+
+#include "graphicswidgets.h"
+#include <QGraphicsLinearLayout>
+#include <QGraphicsGridLayout>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+QML_DECLARE_INTERFACE(QGraphicsLayoutItem);
+QML_DECLARE_INTERFACE(QGraphicsLayout);
+
+class QGraphicsLinearLayoutStretchItemObject : public QObject, public QGraphicsLayoutItem
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayoutItem)
+public:
+ QGraphicsLinearLayoutStretchItemObject(QObject *parent = 0);
+
+ virtual QSizeF sizeHint(Qt::SizeHint, const QSizeF &) const;
+};
+QML_DECLARE_TYPE(QGraphicsLinearLayoutStretchItemObject);
+
+//TODO:
+// -content margins
+// -per-item spacing (does this need to be exposed?)
+// -per-item alignment
+class LinearLayoutAttached;
+class QGraphicsLinearLayoutObject : public QObject, public QGraphicsLinearLayout
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayout QGraphicsLayoutItem)
+
+ Q_PROPERTY(QmlList<QGraphicsLayoutItem *> *children READ children)
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+ Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing)
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QGraphicsLinearLayoutObject(QObject * = 0);
+ ~QGraphicsLinearLayoutObject();
+
+ QmlList<QGraphicsLayoutItem *> *children() { return &_children; }
+
+ static QObject *qmlAttachedProperties(QObject *);
+
+private Q_SLOTS:
+ void updateStretch(QGraphicsLayoutItem*,int);
+ void updateAlignment(QGraphicsLayoutItem*,Qt::Alignment);
+
+private:
+ friend class LinearLayoutAttached;
+ void clearChildren();
+ void insertLayoutItem(int, QGraphicsLayoutItem *);
+ static QHash<QGraphicsLayoutItem*, QObject*> attachedProperties;
+
+ class ChildList : public QmlList<QGraphicsLayoutItem *>
+ {
+ public:
+ ChildList(QGraphicsLinearLayoutObject *o)
+ : obj(o) {}
+
+ virtual void append(QGraphicsLayoutItem *item)
+ {
+ insert(-1, item);
+ }
+ virtual void clear() { obj->clearChildren(); }
+ virtual int count() const { return obj->count(); }
+ virtual void removeAt(int i) { obj->removeAt(i); }
+ virtual QGraphicsLayoutItem *at(int i) const { return obj->itemAt(i); }
+ virtual void insert(int i, QGraphicsLayoutItem *item) { obj->insertLayoutItem(i, item); }
+
+ private:
+ QGraphicsLinearLayoutObject *obj;
+ };
+
+ ChildList _children;
+};
+QML_DECLARE_TYPE(QGraphicsLinearLayoutObject);
+
+//TODO:
+// -content margins
+// -column and row specific settings:
+// -alignment
+// -fixed/min/max/preferred width
+// -spacing
+// -stretch
+class QGraphicsGridLayoutObject : public QObject, public QGraphicsGridLayout
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayout QGraphicsLayoutItem)
+
+ Q_PROPERTY(QmlList<QGraphicsLayoutItem *> *children READ children)
+ Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing)
+ Q_PROPERTY(qreal verticalSpacing READ verticalSpacing WRITE setVerticalSpacing)
+ Q_PROPERTY(qreal horizontalSpacing READ horizontalSpacing WRITE setHorizontalSpacing)
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QGraphicsGridLayoutObject(QObject * = 0);
+ ~QGraphicsGridLayoutObject();
+
+ QmlList<QGraphicsLayoutItem *> *children() { return &_children; }
+
+ qreal spacing() const;
+
+ static QObject *qmlAttachedProperties(QObject *);
+
+private:
+ friend class GraphicsLayoutAttached;
+ void addWidget(QGraphicsWidget *);
+ void clearChildren();
+ void addLayoutItem(QGraphicsLayoutItem *);
+ static QHash<QGraphicsLayoutItem*, QObject*> attachedProperties;
+
+ class ChildList : public QmlList<QGraphicsLayoutItem *>
+ {
+ public:
+ ChildList(QGraphicsGridLayoutObject *o)
+ : obj(o) {}
+
+ virtual void append(QGraphicsLayoutItem *o)
+ {
+ obj->addLayoutItem(o);
+ }
+ virtual void clear() { obj->clearChildren(); }
+ virtual int count() const { return obj->count(); }
+ virtual void removeAt(int i) { obj->removeAt(i); }
+ virtual QGraphicsLayoutItem *at(int i) const { return obj->itemAt(i); }
+ //XXX GridLayout doesn't have an insert, so for now we treat it as an append.
+ // this is obviously potenitally dangerous -- perhaps should be a concrete
+ // list with no relation to layout index, etc at all.
+ virtual void insert(int, QGraphicsLayoutItem *item) { append(item); }
+
+ private:
+ QGraphicsGridLayoutObject *obj;
+ };
+
+ ChildList _children;
+};
+QML_DECLARE_TYPE(QGraphicsGridLayoutObject);
+
+#endif // GRAPHICSLAYOUTS_H
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/widgets/graphicswidgets.cpp b/src/declarative/widgets/graphicswidgets.cpp
new file mode 100644
index 0000000..b808807
--- /dev/null
+++ b/src/declarative/widgets/graphicswidgets.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "graphicswidgets.h"
+
+QT_BEGIN_NAMESPACE
+
+//### the single (default) property could alternatively be added to graphics view directly
+class QGraphicsViewDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QGraphicsScene *scene READ scene WRITE setScene)
+ Q_CLASSINFO("DefaultProperty", "scene")
+public:
+ QGraphicsViewDeclarativeUI(QObject *other) : QObject(other) {}
+
+ QGraphicsScene *scene() const { return static_cast<QGraphicsView *>(parent())->scene(); }
+ void setScene(QGraphicsScene *scene)
+ {
+ static_cast<QGraphicsView *>(parent())->setScene(scene);
+ }
+};
+QML_DEFINE_EXTENDED_TYPE(QGraphicsView,QGraphicsView,QGraphicsViewDeclarativeUI);
+
+class QGraphicsSceneDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QmlList<QObject *> *children READ children)
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QGraphicsSceneDeclarativeUI(QObject *other) : QObject(other), _children(other) {}
+
+ QmlList<QObject *> *children() { return &_children; }
+
+private:
+ class Children : public QmlConcreteList<QObject *>
+ {
+ public:
+ Children(QObject *scene) : q(scene) {}
+ virtual void append(QObject *o)
+ {
+ insert(-1, o);
+ }
+ virtual void clear()
+ {
+ for (int i = 0; i < count(); ++i)
+ if (QGraphicsWidget *w = qobject_cast<QGraphicsWidget *>(at(i)))
+ static_cast<QGraphicsScene *>(q)->removeItem(w);
+ QmlConcreteList<QObject *>::clear();
+ }
+ virtual void removeAt(int i)
+ {
+ if (QGraphicsWidget *w = qobject_cast<QGraphicsWidget *>(at(i)))
+ static_cast<QGraphicsScene *>(q)->removeItem(w);
+ QmlConcreteList<QObject *>::removeAt(i);
+ }
+ virtual void insert(int i, QObject *o)
+ {
+ QmlConcreteList<QObject *>::insert(i, o);
+
+ //XXX are there any cases when insertion should be different from appension?
+ if (QGraphicsWidget *w = qobject_cast<QGraphicsWidget *>(o))
+ static_cast<QGraphicsScene *>(q)->addItem(w);
+ //else if (QWidget *w = qobject_cast<QWidget *>(o))
+ // static_cast<QGraphicsScene *>(q)->addWidget(w);
+ //else
+ // qWarning() << "Can't add" << o << "to a QGraphicsScene";
+ }
+ private:
+ QObject *q;
+ };
+ Children _children;
+};
+QML_DEFINE_EXTENDED_TYPE(QGraphicsScene,QGraphicsScene,QGraphicsSceneDeclarativeUI);
+
+class QGraphicsWidgetDeclarativeUI : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QmlList<QObject *> *data READ data)
+ Q_PROPERTY(QmlList<QGraphicsItem *> *children READ children)
+ Q_PROPERTY(QGraphicsLayout *layout READ layout WRITE setLayout)
+ Q_CLASSINFO("DefaultProperty", "children")
+public:
+ QGraphicsWidgetDeclarativeUI(QObject *other) : QObject(other), _widgets(this) {}
+
+ QmlList<QObject *> *data() { return &_data; }
+
+ QmlList<QGraphicsItem *> *children() { return &_widgets; }
+
+ QGraphicsLayout *layout() const { return static_cast<QGraphicsWidget *>(parent())->layout(); }
+ void setLayout(QGraphicsLayout *lo)
+ {
+ static_cast<QGraphicsWidget *>(parent())->setLayout(lo);
+ }
+
+private:
+ friend class WidgetList;
+ void setItemParent(QGraphicsItem *wid)
+ {
+ wid->setParentItem(static_cast<QGraphicsWidget *>(parent()));
+ }
+
+ //###
+ void clearWidget()
+ {
+ }
+
+ class WidgetList : public QmlConcreteList<QGraphicsItem *>
+ {
+ public:
+ WidgetList(QGraphicsWidgetDeclarativeUI *o)
+ : obj(o) {}
+
+ virtual void append(QGraphicsItem *w) { QmlConcreteList<QGraphicsItem *>::append(w); obj->setItemParent(w); }
+ virtual void clear() { QmlConcreteList<QGraphicsItem *>::clear(); obj->clearWidget(); }
+ virtual void removeAt(int i) { QmlConcreteList<QGraphicsItem *>::removeAt(i); } //XXX
+ virtual void insert(int i, QGraphicsItem *item) { QmlConcreteList<QGraphicsItem *>::insert(i, item); obj->setItemParent(item); }
+
+ private:
+ QGraphicsWidgetDeclarativeUI *obj;
+ };
+ WidgetList _widgets;
+ QmlConcreteList<QObject *> _data;
+};
+
+QML_DEFINE_EXTENDED_TYPE(QGraphicsWidget,QGraphicsWidget,QGraphicsWidgetDeclarativeUI);
+
+QML_DEFINE_INTERFACE(QGraphicsItem);
+
+#include "graphicswidgets.moc"
+
+QT_END_NAMESPACE
diff --git a/src/declarative/widgets/graphicswidgets.h b/src/declarative/widgets/graphicswidgets.h
new file mode 100644
index 0000000..47a753a
--- /dev/null
+++ b/src/declarative/widgets/graphicswidgets.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRAPHICSWIDGETS_H
+#define GRAPHICSWIDGETS_H
+
+#include <qml.h>
+#include <QGraphicsScene>
+#include <QGraphicsView>
+#include <QGraphicsWidget>
+#include <QGraphicsItem>
+
+QT_BEGIN_NAMESPACE
+
+QML_DECLARE_TYPE(QGraphicsView);
+QML_DECLARE_TYPE_HASMETATYPE(QGraphicsScene);
+QML_DECLARE_TYPE(QGraphicsWidget);
+QML_DECLARE_INTERFACE_HASMETATYPE(QGraphicsItem);
+
+QT_END_NAMESPACE
+
+#endif // GRAPHICSWIDGETS_H
diff --git a/src/declarative/widgets/widgets.pri b/src/declarative/widgets/widgets.pri
new file mode 100644
index 0000000..41c50d8
--- /dev/null
+++ b/src/declarative/widgets/widgets.pri
@@ -0,0 +1,10 @@
+SOURCES += \
+ widgets/graphicswidgets.cpp \
+ widgets/graphicslayouts.cpp \
+
+HEADERS += \
+ widgets/graphicswidgets.h \
+ widgets/graphicslayouts.h \
+
+
+
diff --git a/src/gui/animation/animation.pri b/src/gui/animation/animation.pri
new file mode 100644
index 0000000..27763ca
--- /dev/null
+++ b/src/gui/animation/animation.pri
@@ -0,0 +1,3 @@
+# Qt gui animation module
+
+SOURCES += animation/qguivariantanimation.cpp
diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp
new file mode 100644
index 0000000..ed18caa
--- /dev/null
+++ b/src/gui/animation/qguivariantanimation.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_ANIMATION
+
+#ifdef QT_EXPERIMENTAL_SOLUTION
+# include "qvariantanimation.h"
+# include "qvariantanimation_p.h"
+#else
+#include <QtCore/qvariantanimation.h>
+#include <private/qvariantanimation_p.h>
+#endif
+
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_NAMESPACE
+
+template<> Q_INLINE_TEMPLATE QColor _q_interpolate(const QColor &f,const QColor &t, qreal progress)
+{
+ return QColor(_q_interpolate(f.red(), t.red(), progress),
+ _q_interpolate(f.green(), t.green(), progress),
+ _q_interpolate(f.blue(), t.blue(), progress),
+ _q_interpolate(f.alpha(), t.alpha(), progress));
+}
+
+static int qRegisterGuiGetInterpolator()
+{
+ qRegisterAnimationInterpolator<QColor>(_q_interpolateVariant<QColor>);
+ return 1;
+}
+Q_CONSTRUCTOR_FUNCTION(qRegisterGuiGetInterpolator)
+
+static int qUnregisterGuiGetInterpolator()
+{
+ qRegisterAnimationInterpolator<QColor>(0);
+ return 1;
+}
+Q_DESTRUCTOR_FUNCTION(qUnregisterGuiGetInterpolator)
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 743c16d..ce635d6 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -1002,7 +1002,12 @@ QGraphicsItem::~QGraphicsItem()
d_ptr->setParentItemHelper(0, /* deleting = */ true);
if (d_ptr->scene)
d_ptr->scene->d_func()->_q_removeItemLater(this);
-
+
+ if (d_ptr->hasTransform) {
+ delete static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ }
+
delete d_ptr;
qt_dataStore()->data.remove(this);
@@ -2517,7 +2522,24 @@ QTransform QGraphicsItem::transform() const
{
if (!d_ptr->hasTransform)
return QTransform();
- return qVariantValue<QTransform>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform));
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ Q_ASSERT(transformData);
+ if (transformData->dirty) {
+ QGraphicsItem *that = const_cast<QGraphicsItem *>(this);
+ QTransform newTransform;
+ QPointF center = transformData->transformCenter;
+ newTransform.translate(center.x(), center.y());
+ newTransform.rotate(transformData->rotationZ, Qt::ZAxis);
+ newTransform.rotate(transformData->rotationY, Qt::YAxis);
+ newTransform.rotate(transformData->rotationX, Qt::XAxis);
+ newTransform.scale(transformData->scaleX, transformData->scaleY);
+ newTransform *= transformData->baseTransform;
+ newTransform.translate(-center.x(), -center.y());
+ transformData->transform = newTransform;
+ transformData->dirty = false;
+ }
+ return transformData->transform;
}
/*!
@@ -2795,7 +2817,17 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co
*/
void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
{
- QTransform oldTransform = this->transform();
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData) {
+ if (matrix.isIdentity())
+ return;
+ transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue<void *>(transformData));
+ }
+
+ QTransform oldTransform = transformData->baseTransform;
+
QTransform newTransform;
if (!combine)
newTransform = QTransform(matrix);
@@ -2814,8 +2846,9 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
// Update and set the new transformation.
d_ptr->fullUpdateHelper(true, true);
prepareGeometryChange();
- d_ptr->hasTransform = !newTransform.isIdentity();
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform);
+ transformData->baseTransform = newTransform;
+ transformData->dirty = true;
+ d_ptr->hasTransform = true;
d_ptr->invalidateSceneTransformCache();
// Send post-notification.
@@ -2843,7 +2876,17 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
*/
void QGraphicsItem::setTransform(const QTransform &matrix, bool combine)
{
- QTransform oldTransform = this->transform();
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData) {
+ if (matrix.isIdentity())
+ return;
+ transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue<void *>(transformData));
+ }
+
+ QTransform oldTransform = transformData->baseTransform;
+
QTransform newTransform;
if (!combine)
newTransform = matrix;
@@ -2862,8 +2905,10 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine)
// Update and set the new transformation.
d_ptr->fullUpdateHelper(true, true);
prepareGeometryChange();
- d_ptr->hasTransform = !newTransform.isIdentity();
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform);
+ transformData->baseTransform = newTransform;
+ transformData->dirty = true;
+ d_ptr->hasTransform = true;
+ transform(); // ### update transform, bad!
d_ptr->invalidateSceneTransformCache();
// Send post-notification.
@@ -2949,6 +2994,197 @@ void QGraphicsItem::translate(qreal dx, qreal dy)
setTransform(QTransform::fromTranslate(dx, dy), true);
}
+QPointF QGraphicsItem::transformOrigin() const
+{
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData)
+ return QPointF();
+
+ return transformData->transformCenter;
+}
+
+/*!
+ Set a center for all transformation
+*/
+void QGraphicsItem::setTransformOrigin(const QPointF &center)
+{
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData) {
+ if (center.isNull())
+ return;
+ transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue<void *>(transformData));
+ }
+ if (transformData->transformCenter == center)
+ return;
+
+ d_ptr->fullUpdateHelper(true);
+ prepareGeometryChange();
+
+ transformData->transformCenter = center;
+
+ transformData->dirty = true;
+ d_ptr->hasTransform = true;
+ d_ptr->fullUpdateHelper();
+
+}
+
+qreal QGraphicsItem::xScale() const
+{
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData)
+ return 1;
+
+ return transformData->scaleX;
+}
+
+void QGraphicsItem::setXScale(qreal factor)
+{
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData) {
+ if (factor == 1)
+ return;
+ transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue<void *>(transformData));
+ }
+ if (transformData->scaleX == factor)
+ return;
+
+ d_ptr->fullUpdateHelper(true);
+ prepareGeometryChange();
+
+ transformData->scaleX = factor;
+ transformData->dirty = true;
+ d_ptr->hasTransform = true;
+ d_ptr->invalidateSceneTransformCache();
+}
+
+qreal QGraphicsItem::yScale() const
+{
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData)
+ return 1;
+
+ return transformData->scaleY;
+}
+
+void QGraphicsItem::setYScale(qreal factor)
+{
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData) {
+ if (factor == 1)
+ return;
+ transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue<void *>(transformData));
+ }
+ if (transformData->scaleY == factor)
+ return;
+
+ d_ptr->fullUpdateHelper(true);
+ prepareGeometryChange();
+
+ transformData->scaleY = factor;
+ transformData->dirty = true;
+ d_ptr->hasTransform = true;
+ d_ptr->invalidateSceneTransformCache();
+}
+
+qreal QGraphicsItem::xRotation() const
+{
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData)
+ return 0;
+ return transformData->rotationX;
+}
+
+void QGraphicsItem::setXRotation(qreal angle)
+{
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData) {
+ if (qFuzzyCompare(angle + 1, 1))
+ return;
+ transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue<void *>(transformData));
+ }
+
+ d_ptr->fullUpdateHelper(true);
+ prepareGeometryChange();
+
+ transformData->rotationX = angle;
+
+ transformData->dirty = true;
+ d_ptr->hasTransform = true;
+ d_ptr->invalidateSceneTransformCache();
+}
+
+qreal QGraphicsItem::yRotation() const
+{
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData)
+ return 0;
+ return transformData->rotationY;
+}
+
+void QGraphicsItem::setYRotation(qreal angle)
+{
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData) {
+ if (qFuzzyCompare(angle + 1, 1))
+ return;
+ transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue<void *>(transformData));
+ }
+
+ d_ptr->fullUpdateHelper(true);
+ prepareGeometryChange();
+
+ transformData->rotationY = angle;
+
+ transformData->dirty = true;
+ d_ptr->hasTransform = true;
+ d_ptr->invalidateSceneTransformCache();
+}
+
+qreal QGraphicsItem::zRotation() const
+{
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData)
+ return 0;
+ return transformData->rotationZ;
+}
+
+void QGraphicsItem::setZRotation(qreal angle)
+{
+ QGraphicsItemPrivate::TransformData *transformData = static_cast<QGraphicsItemPrivate::TransformData *>(
+ qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform)));
+ if (!transformData) {
+ if (qFuzzyCompare(angle + 1, 1))
+ return;
+ transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, qVariantFromValue<void *>(transformData));
+ }
+
+ d_ptr->fullUpdateHelper(true);
+ prepareGeometryChange();
+
+ transformData->rotationZ = angle;
+
+ transformData->dirty = true;
+ d_ptr->hasTransform = true;
+ d_ptr->invalidateSceneTransformCache();
+}
+
/*!
This virtual function is called twice for all items by the
QGraphicsScene::advance() slot. In the first phase, all items are called
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index b98882d..5ca18dd 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -239,11 +239,27 @@ public:
QTransform itemTransform(const QGraphicsItem *other, bool *ok = 0) const;
void setTransform(const QTransform &matrix, bool combine = false);
void resetTransform();
-
+
+ // ### obsolete?
void rotate(qreal angle);
void scale(qreal sx, qreal sy);
void shear(qreal sh, qreal sv);
void translate(qreal dx, qreal dy);
+
+ // ### experimental
+ QPointF transformOrigin() const;
+ void setTransformOrigin(const QPointF &center);
+ qreal xScale() const;
+ void setXScale(qreal factor);
+ qreal yScale() const;
+ void setYScale(qreal factor);
+ qreal xRotation() const;
+ void setXRotation(qreal angle);
+ qreal yRotation() const;
+ void setYRotation(qreal angle);
+ qreal zRotation() const;
+ void setZRotation(qreal angle);
+
virtual void advance(int phase);
// Stacking order
@@ -404,6 +420,7 @@ private:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsItem::GraphicsItemFlags)
+Q_DECLARE_INTERFACE(QGraphicsItem, "com.trolltech.Qt.QGraphicsItem")
inline void QGraphicsItem::setPos(qreal ax, qreal ay)
{ setPos(QPointF(ax, ay)); }
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 2936cf1..062274f 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -91,6 +91,15 @@ class Q_AUTOTEST_EXPORT QGraphicsItemPrivate
{
Q_DECLARE_PUBLIC(QGraphicsItem)
public:
+ struct TransformData
+ {
+ TransformData() : rotationX(0),rotationY(0),rotationZ(0),scaleX(1),scaleY(1), dirty(true) {}
+ QTransform baseTransform;
+ QTransform transform;
+ QPointF transformCenter;
+ qreal rotationX,rotationY,rotationZ,scaleX,scaleY;
+ bool dirty;
+ };
enum Extra {
ExtraTransform,
ExtraToolTip,
@@ -229,7 +238,7 @@ public:
}
}
}
-
+
struct ExtraStruct {
ExtraStruct(Extra type, QVariant value)
: type(type), value(value)
@@ -241,6 +250,7 @@ public:
bool operator<(Extra extra) const
{ return type < extra; }
};
+
QList<ExtraStruct> extras;
QGraphicsItemCache *maybeExtraItemCache() const;
diff --git a/src/gui/graphicsview/qgraphicslayout.h b/src/gui/graphicsview/qgraphicslayout.h
index fad6c3bb..a5f2884 100644
--- a/src/gui/graphicsview/qgraphicslayout.h
+++ b/src/gui/graphicsview/qgraphicslayout.h
@@ -85,6 +85,8 @@ private:
friend class QGraphicsWidget;
};
+Q_DECLARE_INTERFACE(QGraphicsLayout, "com.trolltech.Qt.QGraphicsLayout")
+
#endif
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h
index 31f5d90..0ff3acc 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem.h
+++ b/src/gui/graphicsview/qgraphicslayoutitem.h
@@ -121,6 +121,8 @@ private:
friend class QGraphicsLayout;
};
+Q_DECLARE_INTERFACE(QGraphicsLayoutItem, "com.trolltech.Qt.QGraphicsLayoutItem")
+
inline void QGraphicsLayoutItem::setMinimumSize(qreal aw, qreal ah)
{ setMinimumSize(QSizeF(aw, ah)); }
inline void QGraphicsLayoutItem::setPreferredSize(qreal aw, qreal ah)
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp
index 01b7593..a5b11ff 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp
@@ -976,6 +976,7 @@ void QGraphicsProxyWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *even
}
#endif // QT_NO_CONTEXTMENU
+#ifndef QT_NO_DRAGANDDROP
/*!
\reimp
*/
@@ -1096,6 +1097,7 @@ void QGraphicsProxyWidget::dropEvent(QGraphicsSceneDragDropEvent *event)
}
#endif
}
+#endif
/*!
\reimp
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.h b/src/gui/graphicsview/qgraphicsproxywidget.h
index b2c3c8f..ab8c9da 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.h
+++ b/src/gui/graphicsview/qgraphicsproxywidget.h
@@ -90,10 +90,12 @@ protected:
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
#endif
+#ifndef QT_NO_DRAGANDDROP
void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event);
void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
void dropEvent(QGraphicsSceneDragDropEvent *event);
+#endif
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 69e08d1..bc5c091 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -1329,7 +1329,9 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou
// check if the item we are sending to are disabled (before we send the event)
bool disabled = !item->isEnabled();
bool isWindow = item->isWindow();
- if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick && item != lastMouseGrabberItem) {
+ if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick
+ && item != lastMouseGrabberItem && lastMouseGrabberItem)
+ {
// If this item is different from the item that received the last
// mouse event, and mouseEvent is a doubleclick event, then the
// event is converted to a press. Known limitation:
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 702e0b6..dd681a1 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -291,7 +291,7 @@ QGraphicsWidget::~QGraphicsWidget()
//we check if we have a layout previously
if (d->layout) {
- delete d->layout;
+ QGraphicsLayout *temp = d->layout;
foreach (QGraphicsItem * item, childItems()) {
// In case of a custom layout which doesn't remove and delete items, we ensure that
// the parent layout item does not point to the deleted layout. This code is here to
@@ -302,6 +302,8 @@ QGraphicsWidget::~QGraphicsWidget()
widget->setParentLayoutItem(0);
}
}
+ d->layout = 0;
+ delete temp;
}
// Remove this graphics widget from widgetStyles
diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h
index 34f1c5f..476ca1f 100644
--- a/src/gui/graphicsview/qgraphicswidget.h
+++ b/src/gui/graphicsview/qgraphicswidget.h
@@ -59,6 +59,7 @@ class QGraphicsLayout;
class QGraphicsSceneMoveEvent;
class QGraphicsWidgetPrivate;
class QGraphicsSceneResizeEvent;
+class QGraphicsWidgetAnimator;
class QStyle;
class QStyleOption;
@@ -69,6 +70,7 @@ class QGraphicsWidgetPrivate;
class Q_GUI_EXPORT QGraphicsWidget : public QObject, public QGraphicsItem, public QGraphicsLayoutItem
{
Q_OBJECT
+ Q_INTERFACES(QGraphicsItem QGraphicsLayoutItem)
Q_PROPERTY(QPalette palette READ palette WRITE setPalette)
Q_PROPERTY(QFont font READ font WRITE setFont)
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection)
@@ -81,6 +83,11 @@ class Q_GUI_EXPORT QGraphicsWidget : public QObject, public QGraphicsItem, publi
Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)
Q_PROPERTY(QPointF pos READ pos WRITE setPos)
Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
+ Q_PROPERTY(qreal xScale READ xScale WRITE setXScale)
+ Q_PROPERTY(qreal yScale READ yScale WRITE setYScale)
+ Q_PROPERTY(qreal zRotation READ zRotation WRITE setZRotation)
+ Q_PROPERTY(qreal xRotation READ xRotation WRITE setXRotation)
+ Q_PROPERTY(qreal yRotation READ yRotation WRITE setYRotation)
public:
QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index 1aa6558..329fb01 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -19,6 +19,7 @@ win32:include(kernel/win.pri)
embedded:include(embedded/embedded.pri)
#modules
+include(animation/animation.pri)
include(kernel/kernel.pri)
include(image/image.pri)
include(painting/painting.pri)
@@ -31,6 +32,7 @@ include(itemviews/itemviews.pri)
include(inputmethod/inputmethod.pri)
include(graphicsview/graphicsview.pri)
include(util/util.pri)
+include(statemachine/statemachine.pri)
include(math3d/math3d.pri)
embedded: QT += network
diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h
index d7bf8c3..ffc6fe8 100644
--- a/src/gui/kernel/qaction.h
+++ b/src/gui/kernel/qaction.h
@@ -67,24 +67,24 @@ class Q_GUI_EXPORT QAction : public QObject
Q_DECLARE_PRIVATE(QAction)
Q_ENUMS(MenuRole)
- Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable)
+ Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY changed)
Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled)
- Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
- Q_PROPERTY(QIcon icon READ icon WRITE setIcon)
- Q_PROPERTY(QString text READ text WRITE setText)
- Q_PROPERTY(QString iconText READ iconText WRITE setIconText)
- Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip)
- Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip)
- Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis)
- Q_PROPERTY(QFont font READ font WRITE setFont)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY changed)
+ Q_PROPERTY(QIcon icon READ icon WRITE setIcon NOTIFY changed)
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY changed)
+ Q_PROPERTY(QString iconText READ iconText WRITE setIconText NOTIFY changed)
+ Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY changed)
+ Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip NOTIFY changed)
+ Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis NOTIFY changed)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed)
#ifndef QT_NO_SHORTCUT
- Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut)
- Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext)
- Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat)
+ Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut NOTIFY changed)
+ Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext NOTIFY changed)
+ Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY changed)
#endif
- Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
- Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole)
- Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed)
+ Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed)
+ Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed)
public:
enum MenuRole { NoRole, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole,
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index b9ebf55..27dfab6 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -838,6 +838,9 @@ void QApplicationPrivate::initialize()
// trigger registering of QVariant's GUI types
extern int qRegisterGuiVariant();
qRegisterGuiVariant();
+ // trigger registering of QStateMachine's GUI types
+ extern int qRegisterGuiStateMachine();
+ qRegisterGuiStateMachine();
is_app_running = true; // no longer starting up
@@ -1059,6 +1062,9 @@ QApplication::~QApplication()
QApplicationPrivate::fade_tooltip = false;
QApplicationPrivate::widgetCount = false;
+ // trigger unregistering of QStateMachine's GUI types
+ extern int qUnregisterGuiStateMachine();
+ qUnregisterGuiStateMachine();
// trigger unregistering of QVariant's GUI types
extern int qUnregisterGuiVariant();
qUnregisterGuiVariant();
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index a4d5035..a77325c 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -49,6 +49,7 @@
#include "qmime.h"
#include "qdnd_p.h"
#include "qevent_p.h"
+#include "qdatetime.h"
QT_BEGIN_NAMESPACE
@@ -226,6 +227,17 @@ QMouseEvent *QMouseEvent::createExtendedMouseEvent(Type type, const QPointF &pos
}
/*!
+ \internal
+*/
+QMouseEvent *QMouseEvent::createExtendedMouseEvent(Type type, const QPointF &pos,
+ const QPoint &globalPos, Qt::MouseButton button,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
+ const QDateTime &eventTime)
+{
+ return new QMouseEventEx(type, pos, globalPos, button, buttons, modifiers, eventTime);
+}
+
+/*!
\fn bool QMouseEvent::hasExtendedInfo() const
\internal
*/
@@ -247,13 +259,40 @@ QPointF QMouseEvent::posF() const
return hasExtendedInfo() ? reinterpret_cast<const QMouseEventEx *>(this)->posF : QPointF(pos());
}
+/*!
+ \since 4.6
+
+ Returns the time the mouse event occurred. On many systems and platforms
+ this is equivalent to QDateTime::currentDateTime().
+*/
+QDateTime QMouseEvent::eventDateTime() const
+{
+ if(hasExtendedInfo() && reinterpret_cast<const QMouseEventEx *>(this)->timeSet) {
+ return reinterpret_cast<const QMouseEventEx *>(this)->time;
+ } else {
+ return QDateTime::currentDateTime();
+ }
+}
+
/*!
\internal
*/
QMouseEventEx::QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers)
- : QMouseEvent(type, pos.toPoint(), globalPos, button, buttons, modifiers), posF(pos)
+ : QMouseEvent(type, pos.toPoint(), globalPos, button, buttons, modifiers), posF(pos), timeSet(false)
+{
+ d = reinterpret_cast<QEventPrivate *>(this);
+}
+
+/*!
+ \internal
+*/
+QMouseEventEx::QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
+ Qt::MouseButton button, Qt::MouseButtons buttons,
+ Qt::KeyboardModifiers modifiers,
+ const QDateTime &eventTime)
+ : QMouseEvent(type, pos.toPoint(), globalPos, button, buttons, modifiers), posF(pos), timeSet(true), time(eventTime)
{
d = reinterpret_cast<QEventPrivate *>(this);
}
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 449730d..150e139 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -93,8 +93,13 @@ public:
static QMouseEvent *createExtendedMouseEvent(Type type, const QPointF &pos,
const QPoint &globalPos, Qt::MouseButton button,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
+ static QMouseEvent *createExtendedMouseEvent(Type type, const QPointF &pos,
+ const QPoint &globalPos, Qt::MouseButton button,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
+ const QDateTime &eventTime);
inline bool hasExtendedInfo() const { return reinterpret_cast<const QMouseEvent *>(d) == this; }
QPointF posF() const;
+ QDateTime eventDateTime() const;
#ifdef QT3_SUPPORT
QT3_SUPPORT_CONSTRUCTOR QMouseEvent(Type type, const QPoint &pos, Qt::ButtonState button, int state);
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index 8e762d6..484f335 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -43,6 +43,7 @@
#define QEVENT_P_H
#include <QtCore/qglobal.h>
+#include <QtCore/qdatetime.h>
QT_BEGIN_NAMESPACE
@@ -82,10 +83,15 @@ public:
QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers);
+ QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
+ Qt::MouseButton button, Qt::MouseButtons buttons,
+ Qt::KeyboardModifiers modifiers, const QDateTime &eventTime);
~QMouseEventEx();
protected:
QPointF posF;
+ bool timeSet:1;
+ QDateTime time;
friend class QMouseEvent;
};
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index fdd0c21..4cf695e 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -6930,7 +6930,7 @@ static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
}
void qt_build_pow_tables() {
- qreal smoothing = 1.7;
+ qreal smoothing = qreal(1.7);
#ifdef Q_WS_MAC
// decided by testing a few things on an iMac, should probably get this from the
@@ -6952,17 +6952,17 @@ void qt_build_pow_tables() {
}
#else
for (int i=0; i<256; ++i) {
- qt_pow_rgb_gamma[i] = uchar(qRound(pow(i / 255.0, smoothing) * 255));
- qt_pow_rgb_invgamma[i] = uchar(qRound(pow(i / 255.0, 1 / smoothing) * 255));
+ qt_pow_rgb_gamma[i] = uchar(qRound(pow(i / qreal(255.0), smoothing) * 255));
+ qt_pow_rgb_invgamma[i] = uchar(qRound(pow(i / qreal(255.), 1 / smoothing) * 255));
}
#endif
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
- const qreal gray_gamma = 2.31;
+ const qreal gray_gamma = qreal(2.31);
for (int i=0; i<256; ++i)
- qt_pow_gamma[i] = uint(qRound(pow(i / 255.0, gray_gamma) * 2047));
+ qt_pow_gamma[i] = uint(qRound(pow(i / qreal(255.), gray_gamma) * 2047));
for (int i=0; i<2048; ++i)
- qt_pow_invgamma[i] = uchar(qRound(pow(i / 2047.0, 1 / gray_gamma) * 255));
+ qt_pow_invgamma[i] = uchar(qRound(pow(i / qreal(2047.), 1 / gray_gamma) * 255));
#endif
}
diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp
index 230d30b..4020593 100644
--- a/src/gui/painting/qdrawutil.cpp
+++ b/src/gui/painting/qdrawutil.cpp
@@ -1039,7 +1039,7 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs,
#endif
/*!
- \struct QMargins
+ \class QMargins
\since 4.6
Holds the borders used to split a pixmap into nine segments in order to
@@ -1050,7 +1050,7 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs,
*/
/*!
- \struct QTileRules
+ \class QTileRules
\since 4.6
Holds the rules used to draw a pixmap or image split into nine segments,
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 9b10f3c..601e481 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -2049,7 +2049,7 @@ QPainterPath QPainterPath::translated(qreal dx, qreal dy) const
}
/*!
- \fn void QPainterPath::translated(const QPointF &offset)
+ \fn void QPainterPath::translated(const QPointF &offset) const
\overload
\since 4.6
diff --git a/src/gui/statemachine/qbasickeyeventtransition.cpp b/src/gui/statemachine/qbasickeyeventtransition.cpp
new file mode 100644
index 0000000..7821feb
--- /dev/null
+++ b/src/gui/statemachine/qbasickeyeventtransition.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qbasickeyeventtransition_p.h"
+#include <QtGui/qevent.h>
+#include <qdebug.h>
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qabstracttransition_p.h"
+#else
+# include <private/qabstracttransition_p.h>
+#endif
+
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QBasicKeyEventTransition
+
+ \brief The QBasicKeyEventTransition class provides a transition for Qt key events.
+*/
+
+class QBasicKeyEventTransitionPrivate : public QAbstractTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QBasicKeyEventTransition)
+public:
+ QBasicKeyEventTransitionPrivate();
+
+ static QBasicKeyEventTransitionPrivate *get(QBasicKeyEventTransition *q);
+
+ QEvent::Type eventType;
+ int key;
+ Qt::KeyboardModifiers modifiersMask;
+};
+
+QBasicKeyEventTransitionPrivate::QBasicKeyEventTransitionPrivate()
+{
+ eventType = QEvent::None;
+ key = 0;
+ modifiersMask = Qt::NoModifier;
+}
+
+QBasicKeyEventTransitionPrivate *QBasicKeyEventTransitionPrivate::get(QBasicKeyEventTransition *q)
+{
+ return q->d_func();
+}
+
+/*!
+ Constructs a new key event transition with the given \a sourceState.
+*/
+QBasicKeyEventTransition::QBasicKeyEventTransition(QState *sourceState)
+ : QAbstractTransition(*new QBasicKeyEventTransitionPrivate, sourceState)
+{
+}
+
+/*!
+ Constructs a new event transition for events of the given \a type for the
+ given \a key, with the given \a sourceState.
+*/
+QBasicKeyEventTransition::QBasicKeyEventTransition(QEvent::Type type, int key,
+ QState *sourceState)
+ : QAbstractTransition(*new QBasicKeyEventTransitionPrivate, sourceState)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->eventType = type;
+ d->key = key;
+}
+
+/*!
+ Constructs a new event transition for events of the given \a type for the
+ given \a key, with the given \a modifiersMask and \a sourceState.
+*/
+QBasicKeyEventTransition::QBasicKeyEventTransition(QEvent::Type type, int key,
+ Qt::KeyboardModifiers modifiersMask,
+ QState *sourceState)
+ : QAbstractTransition(*new QBasicKeyEventTransitionPrivate, sourceState)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->eventType = type;
+ d->key = key;
+ d->modifiersMask = modifiersMask;
+}
+
+/*!
+ Destroys this event transition.
+*/
+QBasicKeyEventTransition::~QBasicKeyEventTransition()
+{
+}
+
+/*!
+ Returns the event type that this key event transition is associated with.
+*/
+QEvent::Type QBasicKeyEventTransition::eventType() const
+{
+ Q_D(const QBasicKeyEventTransition);
+ return d->eventType;
+}
+
+/*!
+ Sets the event \a type that this key event transition is associated with.
+*/
+void QBasicKeyEventTransition::setEventType(QEvent::Type type)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->eventType = type;
+}
+
+/*!
+ Returns the key that this key event transition checks for.
+*/
+int QBasicKeyEventTransition::key() const
+{
+ Q_D(const QBasicKeyEventTransition);
+ return d->key;
+}
+
+/*!
+ Sets the key that this key event transition will check for.
+*/
+void QBasicKeyEventTransition::setKey(int key)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->key = key;
+}
+
+/*!
+ Returns the keyboard modifiers mask that this key event transition checks
+ for.
+*/
+Qt::KeyboardModifiers QBasicKeyEventTransition::modifiersMask() const
+{
+ Q_D(const QBasicKeyEventTransition);
+ return d->modifiersMask;
+}
+
+/*!
+ Sets the keyboard modifiers mask that this key event transition will check
+ for.
+*/
+void QBasicKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->modifiersMask = modifiersMask;
+}
+
+/*!
+ \reimp
+*/
+bool QBasicKeyEventTransition::eventTest(QEvent *event) const
+{
+ Q_D(const QBasicKeyEventTransition);
+ if (event->type() == d->eventType) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(event);
+ return (ke->key() == d->key)
+ && ((ke->modifiers() & d->modifiersMask) == d->modifiersMask);
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QBasicKeyEventTransition::onTransition(QEvent *)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/statemachine/qbasickeyeventtransition_p.h b/src/gui/statemachine/qbasickeyeventtransition_p.h
new file mode 100644
index 0000000..0d08da0
--- /dev/null
+++ b/src/gui/statemachine/qbasickeyeventtransition_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBASICKEYEVENTTRANSITION_P_H
+#define QBASICKEYEVENTTRANSITION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+// Qt
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qabstracttransition.h"
+#else
+# include <QtCore/qabstracttransition.h>
+#endif
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBasicKeyEventTransitionPrivate;
+class Q_AUTOTEST_EXPORT QBasicKeyEventTransition : public QAbstractTransition
+{
+ Q_OBJECT
+public:
+ QBasicKeyEventTransition(QState *sourceState = 0);
+ QBasicKeyEventTransition(QEvent::Type type, int key, QState *sourceState = 0);
+ QBasicKeyEventTransition(QEvent::Type type, int key,
+ Qt::KeyboardModifiers modifiersMask,
+ QState *sourceState = 0);
+ ~QBasicKeyEventTransition();
+
+ QEvent::Type eventType() const;
+ void setEventType(QEvent::Type type);
+
+ int key() const;
+ void setKey(int key);
+
+ Qt::KeyboardModifiers modifiersMask() const;
+ void setModifiersMask(Qt::KeyboardModifiers modifiers);
+
+protected:
+ bool eventTest(QEvent *event) const;
+ void onTransition(QEvent *);
+
+private:
+ Q_DISABLE_COPY(QBasicKeyEventTransition)
+ Q_DECLARE_PRIVATE(QBasicKeyEventTransition)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/statemachine/qbasicmouseeventtransition.cpp b/src/gui/statemachine/qbasicmouseeventtransition.cpp
new file mode 100644
index 0000000..0cb727e
--- /dev/null
+++ b/src/gui/statemachine/qbasicmouseeventtransition.cpp
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qbasicmouseeventtransition_p.h"
+#include <QtGui/qevent.h>
+#include <QtGui/qpainterpath.h>
+#include <qdebug.h>
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qabstracttransition_p.h"
+#else
+# include <private/qabstracttransition_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QBasicMouseEventTransition
+
+ \brief The QBasicMouseEventTransition class provides a transition for Qt mouse events.
+*/
+
+class QBasicMouseEventTransitionPrivate : public QAbstractTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QBasicMouseEventTransition)
+public:
+ QBasicMouseEventTransitionPrivate();
+
+ static QBasicMouseEventTransitionPrivate *get(QBasicMouseEventTransition *q);
+
+ QEvent::Type eventType;
+ Qt::MouseButton button;
+ Qt::KeyboardModifiers modifiersMask;
+ QPainterPath path;
+};
+
+QBasicMouseEventTransitionPrivate::QBasicMouseEventTransitionPrivate()
+{
+ eventType = QEvent::None;
+ button = Qt::NoButton;
+}
+
+QBasicMouseEventTransitionPrivate *QBasicMouseEventTransitionPrivate::get(QBasicMouseEventTransition *q)
+{
+ return q->d_func();
+}
+
+/*!
+ Constructs a new mouse event transition with the given \a sourceState.
+*/
+QBasicMouseEventTransition::QBasicMouseEventTransition(QState *sourceState)
+ : QAbstractTransition(*new QBasicMouseEventTransitionPrivate, sourceState)
+{
+}
+
+/*!
+ Constructs a new mouse event transition for events of the given \a type.
+*/
+QBasicMouseEventTransition::QBasicMouseEventTransition(QEvent::Type type,
+ Qt::MouseButton button,
+ QState *sourceState)
+ : QAbstractTransition(*new QBasicMouseEventTransitionPrivate, sourceState)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->eventType = type;
+ d->button = button;
+}
+
+/*!
+ Destroys this mouse event transition.
+*/
+QBasicMouseEventTransition::~QBasicMouseEventTransition()
+{
+}
+
+/*!
+ Returns the event type that this mouse event transition is associated with.
+*/
+QEvent::Type QBasicMouseEventTransition::eventType() const
+{
+ Q_D(const QBasicMouseEventTransition);
+ return d->eventType;
+}
+
+/*!
+ Sets the event \a type that this mouse event transition is associated with.
+*/
+void QBasicMouseEventTransition::setEventType(QEvent::Type type)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->eventType = type;
+}
+
+/*!
+ Returns the button that this mouse event transition checks for.
+*/
+Qt::MouseButton QBasicMouseEventTransition::button() const
+{
+ Q_D(const QBasicMouseEventTransition);
+ return d->button;
+}
+
+/*!
+ Sets the button that this mouse event transition will check for.
+*/
+void QBasicMouseEventTransition::setButton(Qt::MouseButton button)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->button = button;
+}
+
+/*!
+ Returns the keyboard modifiers mask that this mouse event transition checks
+ for.
+*/
+Qt::KeyboardModifiers QBasicMouseEventTransition::modifiersMask() const
+{
+ Q_D(const QBasicMouseEventTransition);
+ return d->modifiersMask;
+}
+
+/*!
+ Sets the keyboard modifiers mask that this mouse event transition will check
+ for.
+*/
+void QBasicMouseEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->modifiersMask = modifiersMask;
+}
+
+/*!
+ Returns the path for this mouse event transition.
+*/
+QPainterPath QBasicMouseEventTransition::path() const
+{
+ Q_D(const QBasicMouseEventTransition);
+ return d->path;
+}
+
+/*!
+ Sets the path for this mouse event transition.
+*/
+void QBasicMouseEventTransition::setPath(const QPainterPath &path)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->path = path;
+}
+
+/*!
+ \reimp
+*/
+bool QBasicMouseEventTransition::eventTest(QEvent *event) const
+{
+ Q_D(const QBasicMouseEventTransition);
+ if (event->type() == d->eventType) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ return (me->button() == d->button)
+ && ((me->modifiers() & d->modifiersMask) == d->modifiersMask)
+ && (d->path.isEmpty() || d->path.contains(me->pos()));
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QBasicMouseEventTransition::onTransition(QEvent *)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/statemachine/qbasicmouseeventtransition_p.h b/src/gui/statemachine/qbasicmouseeventtransition_p.h
new file mode 100644
index 0000000..20c7f8f
--- /dev/null
+++ b/src/gui/statemachine/qbasicmouseeventtransition_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBASICMOUSEEVENTTRANSITION_P_H
+#define QBASICMOUSEEVENTTRANSITION_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.
+//
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qabstracttransition.h"
+#else
+# include <QtCore/qabstracttransition.h>
+#endif
+
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPainterPath;
+
+class QBasicMouseEventTransitionPrivate;
+class Q_AUTOTEST_EXPORT QBasicMouseEventTransition : public QAbstractTransition
+{
+ Q_OBJECT
+public:
+ QBasicMouseEventTransition(QState *sourceState = 0);
+ QBasicMouseEventTransition(QEvent::Type type, Qt::MouseButton button,
+ QState *sourceState = 0);
+ ~QBasicMouseEventTransition();
+
+ QEvent::Type eventType() const;
+ void setEventType(QEvent::Type type);
+
+ Qt::MouseButton button() const;
+ void setButton(Qt::MouseButton button);
+
+ Qt::KeyboardModifiers modifiersMask() const;
+ void setModifiersMask(Qt::KeyboardModifiers modifiers);
+
+ QPainterPath path() const;
+ void setPath(const QPainterPath &path);
+
+protected:
+ bool eventTest(QEvent *event) const;
+ void onTransition(QEvent *);
+
+private:
+ Q_DISABLE_COPY(QBasicMouseEventTransition)
+ Q_DECLARE_PRIVATE(QBasicMouseEventTransition)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/statemachine/qguistatemachine.cpp b/src/gui/statemachine/qguistatemachine.cpp
new file mode 100644
index 0000000..d30265a
--- /dev/null
+++ b/src/gui/statemachine/qguistatemachine.cpp
@@ -0,0 +1,534 @@
+ /****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifdef QT_STATEMACHINE_SOLUTION
+#include "qstatemachine.h"
+#include "qstatemachine_p.h"
+#else
+#include <QtCore/qstatemachine.h>
+#include <private/qstatemachine_p.h>
+#endif
+#include <QtGui/qevent.h>
+#include <QtGui/qgraphicssceneevent.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler();
+
+static QEvent *cloneEvent(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ return new QMouseEvent(*static_cast<QMouseEvent*>(e));
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ return new QKeyEvent(*static_cast<QKeyEvent*>(e));
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ return new QFocusEvent(*static_cast<QFocusEvent*>(e));
+ case QEvent::Enter:
+ return new QEvent(*e);
+ case QEvent::Leave:
+ return new QEvent(*e);
+ break;
+ case QEvent::Paint:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Move:
+ return new QMoveEvent(*static_cast<QMoveEvent*>(e));
+ case QEvent::Resize:
+ return new QResizeEvent(*static_cast<QResizeEvent*>(e));
+ case QEvent::Create:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Destroy:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Show:
+ return new QShowEvent(*static_cast<QShowEvent*>(e));
+ case QEvent::Hide:
+ return new QHideEvent(*static_cast<QHideEvent*>(e));
+ case QEvent::Close:
+ return new QCloseEvent(*static_cast<QCloseEvent*>(e));
+ case QEvent::Quit:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ParentChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ParentAboutToChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ThreadChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ return new QEvent(*e);
+
+ case QEvent::ShowToParent:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::HideToParent:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Wheel:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WindowTitleChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WindowIconChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationWindowIconChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationFontChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationLayoutDirectionChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationPaletteChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::PaletteChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Clipboard:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Speech:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::MetaCall:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::SockAct:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WinEventAct:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::DeferredDelete:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::DragEnter:
+ return new QDragEnterEvent(*static_cast<QDragEnterEvent*>(e));
+ case QEvent::DragMove:
+ return new QDragMoveEvent(*static_cast<QDragMoveEvent*>(e));
+ case QEvent::DragLeave:
+ return new QDragLeaveEvent(*static_cast<QDragLeaveEvent*>(e));
+ case QEvent::Drop:
+ return new QDropEvent(*static_cast<QDragMoveEvent*>(e));
+ case QEvent::DragResponse:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ChildAdded:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ChildPolished:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#ifdef QT3_SUPPORT
+ case QEvent::ChildInsertedRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ChildInserted:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LayoutHint:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+ case QEvent::ChildRemoved:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ShowWindowRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::PolishRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Polish:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LayoutRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::UpdateRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::UpdateLater:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::EmbeddingControl:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ActivateControl:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::DeactivateControl:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ContextMenu:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::InputMethod:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::AccessibilityPrepare:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::TabletMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LocaleChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LanguageChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LayoutDirectionChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Style:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::TabletPress:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::TabletRelease:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::OkRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::HelpRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::IconDrag:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::FontChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::EnabledChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ActivationChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::StyleChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::IconTextChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ModifiedChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::MouseTrackingChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::WindowBlocked:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WindowUnblocked:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WindowStateChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ToolTip:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WhatsThis:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::StatusTip:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ActionChanged:
+ case QEvent::ActionAdded:
+ case QEvent::ActionRemoved:
+ return new QActionEvent(*static_cast<QActionEvent*>(e));
+
+ case QEvent::FileOpen:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::Shortcut:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ShortcutOverride:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+#ifdef QT3_SUPPORT
+ case QEvent::Accel:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::AccelAvailable:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+
+ case QEvent::WhatsThisClicked:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ToolBarChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ApplicationActivate:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationDeactivate:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::QueryWhatsThis:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::EnterWhatsThisMode:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LeaveWhatsThisMode:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ZOrderChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::HoverEnter:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::HoverLeave:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::HoverMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::AccessibilityHelp:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::AccessibilityDescription:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+#ifdef QT_KEYPAD_NAVIGATION
+ case QEvent::EnterEditFocus:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LeaveEditFocus:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+ case QEvent::AcceptDropsChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::MenubarUpdated:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ZeroTimerEvent:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::GraphicsSceneMouseDoubleClick: {
+ QGraphicsSceneMouseEvent *me = static_cast<QGraphicsSceneMouseEvent*>(e);
+ QGraphicsSceneMouseEvent *me2 = new QGraphicsSceneMouseEvent(me->type());
+ me2->setWidget(me->widget());
+ me2->setPos(me->pos());
+ me2->setScenePos(me->scenePos());
+ me2->setScreenPos(me->screenPos());
+// ### for all buttons
+ me2->setButtonDownPos(Qt::LeftButton, me->buttonDownPos(Qt::LeftButton));
+ me2->setButtonDownPos(Qt::RightButton, me->buttonDownPos(Qt::RightButton));
+ me2->setButtonDownScreenPos(Qt::LeftButton, me->buttonDownScreenPos(Qt::LeftButton));
+ me2->setButtonDownScreenPos(Qt::RightButton, me->buttonDownScreenPos(Qt::RightButton));
+ me2->setLastPos(me->lastPos());
+ me2->setLastScenePos(me->lastScenePos());
+ me2->setLastScreenPos(me->lastScreenPos());
+ me2->setButtons(me->buttons());
+ me2->setButton(me->button());
+ me2->setModifiers(me->modifiers());
+ return me2;
+ }
+
+ case QEvent::GraphicsSceneContextMenu: {
+ QGraphicsSceneContextMenuEvent *me = static_cast<QGraphicsSceneContextMenuEvent*>(e);
+ QGraphicsSceneContextMenuEvent *me2 = new QGraphicsSceneContextMenuEvent(me->type());
+ me2->setWidget(me->widget());
+ me2->setPos(me->pos());
+ me2->setScenePos(me->scenePos());
+ me2->setScreenPos(me->screenPos());
+ me2->setModifiers(me->modifiers());
+ me2->setReason(me->reason());
+ return me2;
+ }
+
+ case QEvent::GraphicsSceneHoverEnter:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneHoverMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneHoverLeave:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneHelp:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneDragEnter:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneDragMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneDragLeave:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneDrop:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneWheel:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::KeyboardLayoutChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::DynamicPropertyChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::TabletEnterProximity:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::TabletLeaveProximity:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::NonClientAreaMouseMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::NonClientAreaMouseButtonPress:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::NonClientAreaMouseButtonRelease:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::NonClientAreaMouseButtonDblClick:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::MacSizeChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ContentsRectChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::MacGLWindowChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::FutureCallOut:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::GraphicsSceneResize:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneMove: {
+ QGraphicsSceneMoveEvent *me = static_cast<QGraphicsSceneMoveEvent*>(e);
+ QGraphicsSceneMoveEvent *me2 = new QGraphicsSceneMoveEvent();
+ me2->setWidget(me->widget());
+ me2->setNewPos(me->newPos());
+ me2->setOldPos(me->oldPos());
+ return me2;
+ }
+
+ case QEvent::CursorChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ToolTipChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::NetworkReplyUpdated:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::GrabMouse:
+ case QEvent::UngrabMouse:
+ case QEvent::GrabKeyboard:
+ case QEvent::UngrabKeyboard:
+ return new QEvent(*e);
+
+#ifdef QT_MAC_USE_COCOA
+ case QEvent::CocoaRequestModal:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+ case QEvent::User:
+ case QEvent::MaxUser:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ default:
+ ;
+ }
+ return qcoreStateMachineHandler()->cloneEvent(e);
+}
+
+const QStateMachinePrivate::Handler qt_gui_statemachine_handler = {
+ cloneEvent
+};
+
+static const QStateMachinePrivate::Handler *qt_guistatemachine_last_handler = 0;
+int qRegisterGuiStateMachine()
+{
+ qt_guistatemachine_last_handler = QStateMachinePrivate::handler;
+ QStateMachinePrivate::handler = &qt_gui_statemachine_handler;
+ return 1;
+}
+Q_CONSTRUCTOR_FUNCTION(qRegisterGuiStateMachine)
+
+int qUnregisterGuiStateMachine()
+{
+ QStateMachinePrivate::handler = qt_guistatemachine_last_handler;
+ return 1;
+}
+Q_DESTRUCTOR_FUNCTION(qUnregisterGuiStateMachine)
+
+QT_END_NAMESPACE
diff --git a/src/gui/statemachine/qkeyeventtransition.cpp b/src/gui/statemachine/qkeyeventtransition.cpp
new file mode 100644
index 0000000..e6ab11b
--- /dev/null
+++ b/src/gui/statemachine/qkeyeventtransition.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qkeyeventtransition.h"
+#include "qbasickeyeventtransition_p.h"
+#include <QtCore/qwrappedevent.h>
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qeventtransition_p.h"
+#else
+# include <private/qeventtransition_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QKeyEventTransition
+
+ \brief The QKeyEventTransition class provides a transition for key events.
+
+ \since 4.6
+ \ingroup statemachine
+
+ QKeyEventTransition is part of \l{The State Machine Framework}.
+
+ \sa QState::addTransition()
+*/
+
+/*!
+ \property QKeyEventTransition::key
+
+ \brief the key that this key event transition is associated with
+*/
+
+/*!
+ \property QKeyEventTransition::modifiersMask
+
+ \brief the keyboard modifiers mask that this key event transition checks for
+*/
+
+class QKeyEventTransitionPrivate : public QEventTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QKeyEventTransition)
+public:
+ QKeyEventTransitionPrivate() {}
+
+ QBasicKeyEventTransition *transition;
+};
+
+/*!
+ Constructs a new key event transition with the given \a sourceState.
+*/
+QKeyEventTransition::QKeyEventTransition(QState *sourceState)
+ : QEventTransition(*new QKeyEventTransitionPrivate, sourceState)
+{
+ Q_D(QKeyEventTransition);
+ d->transition = new QBasicKeyEventTransition();
+}
+
+/*!
+ Constructs a new key event transition for events of the given \a type for
+ the given \a object, with the given \a key and \a sourceState.
+*/
+QKeyEventTransition::QKeyEventTransition(QObject *object, QEvent::Type type,
+ int key, QState *sourceState)
+ : QEventTransition(*new QKeyEventTransitionPrivate, object, type, sourceState)
+{
+ Q_D(QKeyEventTransition);
+ d->transition = new QBasicKeyEventTransition(type, key);
+}
+
+/*!
+ Constructs a new key event transition for events of the given \a type for
+ the given \a object, with the given \a key, \a targets and \a sourceState.
+*/
+QKeyEventTransition::QKeyEventTransition(QObject *object, QEvent::Type type,
+ int key, const QList<QAbstractState*> &targets,
+ QState *sourceState)
+ : QEventTransition(*new QKeyEventTransitionPrivate, object, type, targets, sourceState)
+{
+ Q_D(QKeyEventTransition);
+ d->transition = new QBasicKeyEventTransition(type, key);
+}
+
+/*!
+ Destroys this key event transition.
+*/
+QKeyEventTransition::~QKeyEventTransition()
+{
+ Q_D(QKeyEventTransition);
+ delete d->transition;
+}
+
+/*!
+ Returns the key that this key event transition checks for.
+*/
+int QKeyEventTransition::key() const
+{
+ Q_D(const QKeyEventTransition);
+ return d->transition->key();
+}
+
+/*!
+ Sets the key that this key event transition will check for.
+*/
+void QKeyEventTransition::setKey(int key)
+{
+ Q_D(QKeyEventTransition);
+ d->transition->setKey(key);
+}
+
+/*!
+ Returns the keyboard modifiers mask that this key event transition checks
+ for.
+*/
+Qt::KeyboardModifiers QKeyEventTransition::modifiersMask() const
+{
+ Q_D(const QKeyEventTransition);
+ return d->transition->modifiersMask();
+}
+
+/*!
+ Sets the keyboard \a modifiers mask that this key event transition will
+ check for.
+*/
+void QKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask)
+{
+ Q_D(QKeyEventTransition);
+ d->transition->setModifiersMask(modifiersMask);
+}
+
+/*!
+ \reimp
+*/
+bool QKeyEventTransition::eventTest(QEvent *event) const
+{
+ Q_D(const QKeyEventTransition);
+ if (!QEventTransition::eventTest(event))
+ return false;
+ QWrappedEvent *we = static_cast<QWrappedEvent*>(event);
+ d->transition->setEventType(we->event()->type());
+ return QAbstractTransitionPrivate::get(d->transition)->callEventTest(we->event());
+}
+
+/*!
+ \reimp
+*/
+void QKeyEventTransition::onTransition(QEvent *event)
+{
+ QEventTransition::onTransition(event);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/statemachine/qkeyeventtransition.h b/src/gui/statemachine/qkeyeventtransition.h
new file mode 100644
index 0000000..3f797f1
--- /dev/null
+++ b/src/gui/statemachine/qkeyeventtransition.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKEYEVENTTRANSITION_H
+#define QKEYEVENTTRANSITION_H
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qeventtransition.h"
+#else
+# include <QtCore/qeventtransition.h>
+#endif
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QKeyEventTransitionPrivate;
+class Q_GUI_EXPORT QKeyEventTransition : public QEventTransition
+{
+ Q_OBJECT
+ Q_PROPERTY(int key READ key WRITE setKey)
+ Q_PROPERTY(Qt::KeyboardModifiers modifiersMask READ modifiersMask WRITE setModifiersMask)
+public:
+ QKeyEventTransition(QState *sourceState = 0);
+ QKeyEventTransition(QObject *object, QEvent::Type type, int key,
+ QState *sourceState = 0);
+ QKeyEventTransition(QObject *object, QEvent::Type type, int key,
+ const QList<QAbstractState*> &targets,
+ QState *sourceState = 0);
+ ~QKeyEventTransition();
+
+ int key() const;
+ void setKey(int key);
+
+ Qt::KeyboardModifiers modifiersMask() const;
+ void setModifiersMask(Qt::KeyboardModifiers modifiers);
+
+protected:
+ void onTransition(QEvent *event);
+ bool eventTest(QEvent *event) const;
+
+private:
+ Q_DISABLE_COPY(QKeyEventTransition)
+ Q_DECLARE_PRIVATE(QKeyEventTransition)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/statemachine/qmouseeventtransition.cpp b/src/gui/statemachine/qmouseeventtransition.cpp
new file mode 100644
index 0000000..3191a2f
--- /dev/null
+++ b/src/gui/statemachine/qmouseeventtransition.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qmouseeventtransition.h"
+#include "qbasicmouseeventtransition_p.h"
+#include <QtCore/qwrappedevent.h>
+#include <QtGui/qpainterpath.h>
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qeventtransition_p.h"
+#else
+# include <private/qeventtransition_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMouseEventTransition
+
+ \brief The QMouseEventTransition class provides a transition for mouse events.
+
+ \since 4.6
+ \ingroup statemachine
+
+ QMouseEventTransition is part of \l{The State Machine Framework}.
+
+ \sa QState::addTransition()
+*/
+
+/*!
+ \property QMouseEventTransition::button
+
+ \brief the button that this mouse event transition is associated with
+*/
+
+/*!
+ \property QMouseEventTransition::modifiersMask
+
+ \brief the keyboard modifiers mask that this mouse event transition checks for
+*/
+
+class QMouseEventTransitionPrivate : public QEventTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QMouseEventTransition)
+public:
+ QMouseEventTransitionPrivate();
+
+ QBasicMouseEventTransition *transition;
+};
+
+QMouseEventTransitionPrivate::QMouseEventTransitionPrivate()
+{
+}
+
+/*!
+ Constructs a new mouse event transition with the given \a sourceState.
+*/
+QMouseEventTransition::QMouseEventTransition(QState *sourceState)
+ : QEventTransition(*new QMouseEventTransitionPrivate, sourceState)
+{
+ Q_D(QMouseEventTransition);
+ d->transition = new QBasicMouseEventTransition();
+}
+
+/*!
+ Constructs a new mouse event transition for events of the given \a type for
+ the given \a object, with the given \a button and \a sourceState.
+*/
+QMouseEventTransition::QMouseEventTransition(QObject *object, QEvent::Type type,
+ Qt::MouseButton button,
+ QState *sourceState)
+ : QEventTransition(*new QMouseEventTransitionPrivate, object, type, sourceState)
+{
+ Q_D(QMouseEventTransition);
+ d->transition = new QBasicMouseEventTransition(type, button);
+}
+
+/*!
+ Constructs a new mouse event transition for events of the given \a type for
+ the given \a object, with the given \a button, \a targets and \a
+ sourceState.
+*/
+QMouseEventTransition::QMouseEventTransition(QObject *object, QEvent::Type type,
+ Qt::MouseButton button,
+ const QList<QAbstractState*> &targets,
+ QState *sourceState)
+ : QEventTransition(*new QMouseEventTransitionPrivate, object, type, targets, sourceState)
+{
+ Q_D(QMouseEventTransition);
+ d->transition = new QBasicMouseEventTransition(type, button);
+}
+
+/*!
+ Destroys this mouse event transition.
+*/
+QMouseEventTransition::~QMouseEventTransition()
+{
+ Q_D(QMouseEventTransition);
+ delete d->transition;
+}
+
+/*!
+ Returns the button that this mouse event transition checks for.
+*/
+Qt::MouseButton QMouseEventTransition::button() const
+{
+ Q_D(const QMouseEventTransition);
+ return d->transition->button();
+}
+
+/*!
+ Sets the \a button that this mouse event transition will check for.
+*/
+void QMouseEventTransition::setButton(Qt::MouseButton button)
+{
+ Q_D(QMouseEventTransition);
+ d->transition->setButton(button);
+}
+
+/*!
+ Returns the keyboard modifiers mask that this mouse event transition checks
+ for.
+*/
+Qt::KeyboardModifiers QMouseEventTransition::modifiersMask() const
+{
+ Q_D(const QMouseEventTransition);
+ return d->transition->modifiersMask();
+}
+
+/*!
+ Sets the keyboard \a modifiers mask that this mouse event transition will
+ check for.
+*/
+void QMouseEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask)
+{
+ Q_D(QMouseEventTransition);
+ d->transition->setModifiersMask(modifiersMask);
+}
+
+/*!
+ Returns the path for this mouse event transition.
+*/
+QPainterPath QMouseEventTransition::path() const
+{
+ Q_D(const QMouseEventTransition);
+ return d->transition->path();
+}
+
+/*!
+ Sets the \a path for this mouse event transition.
+ If a valid path has been set, the transition will only trigger if the mouse
+ event position (QMouseEvent::pos()) is inside the path.
+
+ \sa QPainterPath::contains()
+*/
+void QMouseEventTransition::setPath(const QPainterPath &path)
+{
+ Q_D(QMouseEventTransition);
+ d->transition->setPath(path);
+}
+
+/*!
+ \reimp
+*/
+bool QMouseEventTransition::eventTest(QEvent *event) const
+{
+ Q_D(const QMouseEventTransition);
+ if (!QEventTransition::eventTest(event))
+ return false;
+ QWrappedEvent *we = static_cast<QWrappedEvent*>(event);
+ d->transition->setEventType(we->event()->type());
+ return QAbstractTransitionPrivate::get(d->transition)->callEventTest(we->event());
+}
+
+/*!
+ \reimp
+*/
+void QMouseEventTransition::onTransition(QEvent *event)
+{
+ QEventTransition::onTransition(event);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/statemachine/qmouseeventtransition.h b/src/gui/statemachine/qmouseeventtransition.h
new file mode 100644
index 0000000..eee971e
--- /dev/null
+++ b/src/gui/statemachine/qmouseeventtransition.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSEEVENTTRANSITION_H
+#define QMOUSEEVENTTRANSITION_H
+
+//Qt
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qeventtransition.h"
+#else
+# include <QtCore/qeventtransition.h>
+#endif
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QMouseEventTransitionPrivate;
+class QPainterPath;
+class Q_GUI_EXPORT QMouseEventTransition : public QEventTransition
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::MouseButton button READ button WRITE setButton)
+ Q_PROPERTY(Qt::KeyboardModifiers modifiersMask READ modifiersMask WRITE setModifiersMask)
+public:
+ QMouseEventTransition(QState *sourceState = 0);
+ QMouseEventTransition(QObject *object, QEvent::Type type,
+ Qt::MouseButton button, QState *sourceState = 0);
+ QMouseEventTransition(QObject *object, QEvent::Type type,
+ Qt::MouseButton button,
+ const QList<QAbstractState*> &targets,
+ QState *sourceState = 0);
+ ~QMouseEventTransition();
+
+ Qt::MouseButton button() const;
+ void setButton(Qt::MouseButton button);
+
+ Qt::KeyboardModifiers modifiersMask() const;
+ void setModifiersMask(Qt::KeyboardModifiers modifiers);
+
+ QPainterPath path() const;
+ void setPath(const QPainterPath &path);
+
+protected:
+ void onTransition(QEvent *event);
+ bool eventTest(QEvent *event) const;
+
+private:
+ Q_DISABLE_COPY(QMouseEventTransition)
+ Q_DECLARE_PRIVATE(QMouseEventTransition)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/statemachine/statemachine.pri b/src/gui/statemachine/statemachine.pri
new file mode 100644
index 0000000..2eb1e05
--- /dev/null
+++ b/src/gui/statemachine/statemachine.pri
@@ -0,0 +1,13 @@
+SOURCES += $$PWD/qguistatemachine.cpp
+!contains(DEFINES, QT_NO_STATEMACHINE_EVENTFILTER) {
+ HEADERS += \
+ $$PWD/qkeyeventtransition.h \
+ $$PWD/qmouseeventtransition.h \
+ $$PWD/qbasickeyeventtransition_p.h \
+ $$PWD/qbasicmouseeventtransition_p.h
+ SOURCES += \
+ $$PWD/qkeyeventtransition.cpp \
+ $$PWD/qmouseeventtransition.cpp \
+ $$PWD/qbasickeyeventtransition.cpp \
+ $$PWD/qbasicmouseeventtransition.cpp
+}
diff --git a/src/gui/widgets/qbuttongroup.cpp b/src/gui/widgets/qbuttongroup.cpp
index ebfafe3..8da97bb 100644
--- a/src/gui/widgets/qbuttongroup.cpp
+++ b/src/gui/widgets/qbuttongroup.cpp
@@ -178,10 +178,11 @@
/*!
\fn void QButtonGroup::addButton(QAbstractButton *button);
- Adds the given \a button to the end of the group's internal list of buttons.
- An \a id will be assigned to the button by this QButtonGroup. Automatically
- assigned ids are guaranteed to be negative, starting with -2. If you are also
- assigning your own ids, use positive values to avoid conflicts.
+ Adds the given \a button to the end of the group's internal list
+ of buttons. An id will be assigned to the button by this
+ QButtonGroup. Automatically assigned ids are guaranteed to be
+ negative, starting with -2. If you are also assigning your own
+ ids, use positive values to avoid conflicts.
\sa removeButton() buttons()
*/
@@ -189,8 +190,8 @@
/*!
\fn void QButtonGroup::addButton(QAbstractButton *button, int id);
- Adds the given \a button to the button group, with the given \a
- id. It is recommended to assign only positive ids.
+ Adds the given \a button to the button group, with the given
+ \a id. It is recommended to assign only positive ids.
\sa removeButton() buttons()
*/
diff --git a/src/opengl/gl2paintengineex/qglshader_p.h b/src/opengl/gl2paintengineex/qglshader_p.h
index 1625b84..64c9a42 100644
--- a/src/opengl/gl2paintengineex/qglshader_p.h
+++ b/src/opengl/gl2paintengineex/qglshader_p.h
@@ -81,6 +81,8 @@ SAMPLER_2D_SHADOW.
#include <QtOpenGL>
+#define QGLShader QGLEngineShader
+#define QGLShaderProgram QGLEngineShaderProgram
typedef struct {
GLfloat a;
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index 78aaddb..ad75a5f 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -25,15 +25,17 @@ HEADERS += qgl.h \
qglcolormap.h \
qglpixelbuffer.h \
qglframebufferobject.h \
+ qglshaderprogram.h
SOURCES += qgl.cpp \
qglcolormap.cpp \
qglpixelbuffer.cpp \
qglframebufferobject.cpp \
qglextensions.cpp \
+ qglshaderprogram.cpp
!contains(QT_CONFIG, opengles2) {
- HEADERS += qpaintengine_opengl_p.h qglpixmapfilter_p.h
+ HEADERS += qpaintengine_opengl_p.h qglpixmapfilter_p.h
SOURCES += qpaintengine_opengl.cpp qglpixmapfilter.cpp
}
diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp
index 8357cf9..5ba669b 100644
--- a/src/opengl/qglextensions.cpp
+++ b/src/opengl/qglextensions.cpp
@@ -150,36 +150,158 @@ bool qt_resolve_buffer_extensions(QGLContext *ctx)
bool qt_resolve_glsl_extensions(QGLContext *ctx)
{
+#if defined(QT_OPENGL_ES_2)
+ // The GLSL shader functions are always present in OpenGL/ES 2.0.
+ // The only exceptions are glGetProgramBinaryOES and glProgramBinaryOES.
+ if (!QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glslResolved) {
+ glGetProgramBinaryOES = (_glGetProgramBinaryOES) ctx->getProcAddress(QLatin1String("glGetProgramBinaryOES"));
+ glProgramBinaryOES = (_glProgramBinaryOES) ctx->getProcAddress(QLatin1String("glProgramBinaryOES"));
+ QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glslResolved = true;
+ }
+ return true;
+#else
if (glCreateShader)
return true;
glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShader"));
- glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource"));
- glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShader"));
- glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteShader"));
-
- glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgram"));
- glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachShader"));
- glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachShader"));
- glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgram"));
- glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgram"));
- glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteProgram"));
-
- glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetShaderInfoLog"));
- glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetShaderiv"));
- glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetProgramiv"));
-
- glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocation"));
- glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fv"));
- glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fv"));
- glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fv"));
- glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fv"));
- glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1i"));
-
- return glCreateShader && glShaderSource && glCompileShader && glDeleteProgram &&
- glCreateProgram && glAttachShader && glDetachShader && glLinkProgram && glUseProgram &&
- glDeleteProgram && glGetShaderInfoLog && glGetShaderiv && glGetProgramiv && glGetUniformLocation &&
- glUniform1i && glUniform1fv && glUniform2fv && glUniform3fv && glUniform4fv;
+ if (glCreateShader) {
+ glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource"));
+ glShaderBinary = (_glShaderBinary) ctx->getProcAddress(QLatin1String("glShaderBinary"));
+ glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShader"));
+ glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteShader"));
+ glIsShader = (_glIsShader) ctx->getProcAddress(QLatin1String("glIsShader"));
+
+ glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgram"));
+ glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachShader"));
+ glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachShader"));
+ glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgram"));
+ glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgram"));
+ glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteProgram"));
+ glIsProgram = (_glIsProgram) ctx->getProcAddress(QLatin1String("glIsProgram"));
+
+ glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetShaderInfoLog"));
+ glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetShaderiv"));
+ glGetShaderSource = (_glGetShaderSource) ctx->getProcAddress(QLatin1String("glGetShaderSource"));
+ glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetProgramiv"));
+ glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetProgramInfoLog"));
+
+ glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocation"));
+ glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fv"));
+ glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fv"));
+ glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fv"));
+ glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fv"));
+ glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1i"));
+ glUniform1iv = (_glUniform1iv) ctx->getProcAddress(QLatin1String("glUniform1iv"));
+ glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fv"));
+ glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fv"));
+ glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fv"));
+ glUniformMatrix2x3fv = (_glUniformMatrix2x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x3fv"));
+ glUniformMatrix2x4fv = (_glUniformMatrix2x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x4fv"));
+ glUniformMatrix3x2fv = (_glUniformMatrix3x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x2fv"));
+ glUniformMatrix3x4fv = (_glUniformMatrix3x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x4fv"));
+ glUniformMatrix4x2fv = (_glUniformMatrix4x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x2fv"));
+ glUniformMatrix4x3fv = (_glUniformMatrix4x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x3fv"));
+
+ glBindAttribLocation = (_glBindAttribLocation) ctx->getProcAddress(QLatin1String("glBindAttribLocation"));
+ glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocation"));
+ glVertexAttrib1fv = (_glVertexAttrib1fv) ctx->getProcAddress(QLatin1String("glVertexAttrib1fv"));
+ glVertexAttrib2fv = (_glVertexAttrib2fv) ctx->getProcAddress(QLatin1String("glVertexAttrib2fv"));
+ glVertexAttrib3fv = (_glVertexAttrib3fv) ctx->getProcAddress(QLatin1String("glVertexAttrib3fv"));
+ glVertexAttrib4fv = (_glVertexAttrib4fv) ctx->getProcAddress(QLatin1String("glVertexAttrib4fv"));
+ glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointer"));
+ glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArray"));
+ glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArray"));
+ } else {
+ // We may not have the standard shader functions, but we might
+ // have the older ARB functions instead.
+ glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShaderObjectARB"));
+ glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSourceARB"));
+ glShaderBinary = (_glShaderBinary) ctx->getProcAddress(QLatin1String("glShaderBinaryARB"));
+ glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShaderARB"));
+ glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteObjectARB"));
+ glIsShader = 0;
+
+ glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgramObjectARB"));
+ glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachObjectARB"));
+ glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachObjectARB"));
+ glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgramARB"));
+ glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgramObjectARB"));
+ glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteObjectARB"));
+ glIsProgram = 0;
+
+ glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetInfoLogARB"));
+ glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetObjectParameterivARB"));
+ glGetShaderSource = (_glGetShaderSource) ctx->getProcAddress(QLatin1String("glGetShaderSourceARB"));
+ glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetObjectParameterivARB"));
+ glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetInfoLogARB"));
+
+ glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocationARB"));
+ glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fvARB"));
+ glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fvARB"));
+ glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fvARB"));
+ glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fvARB"));
+ glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1iARB"));
+ glUniform1iv = (_glUniform1iv) ctx->getProcAddress(QLatin1String("glUniform1ivARB"));
+ glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fvARB"));
+ glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fvARB"));
+ glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fvARB"));
+ glUniformMatrix2x3fv = (_glUniformMatrix2x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x3fvARB"));
+ glUniformMatrix2x4fv = (_glUniformMatrix2x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x4fvARB"));
+ glUniformMatrix3x2fv = (_glUniformMatrix3x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x2fvARB"));
+ glUniformMatrix3x4fv = (_glUniformMatrix3x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x4fvARB"));
+ glUniformMatrix4x2fv = (_glUniformMatrix4x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x2fvARB"));
+ glUniformMatrix4x3fv = (_glUniformMatrix4x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x3fvARB"));
+
+ glBindAttribLocation = (_glBindAttribLocation) ctx->getProcAddress(QLatin1String("glBindAttribLocationARB"));
+ glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocationARB"));
+ glVertexAttrib1fv = (_glVertexAttrib1fv) ctx->getProcAddress(QLatin1String("glVertexAttrib1fvARB"));
+ glVertexAttrib2fv = (_glVertexAttrib2fv) ctx->getProcAddress(QLatin1String("glVertexAttrib2fvARB"));
+ glVertexAttrib3fv = (_glVertexAttrib3fv) ctx->getProcAddress(QLatin1String("glVertexAttrib3fvARB"));
+ glVertexAttrib4fv = (_glVertexAttrib4fv) ctx->getProcAddress(QLatin1String("glVertexAttrib4fvARB"));
+ glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointerARB"));
+ glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArrayARB"));
+ glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArrayARB"));
+ }
+
+ // Note: glShaderBinary(), glIsShader(), glIsProgram(), and
+ // glUniformMatrixNxMfv() are optional, but all other functions
+ // are required.
+
+ return glCreateShader &&
+ glShaderSource &&
+ glCompileShader &&
+ glDeleteProgram &&
+ glCreateProgram &&
+ glAttachShader &&
+ glDetachShader &&
+ glLinkProgram &&
+ glUseProgram &&
+ glDeleteProgram &&
+ glGetShaderInfoLog &&
+ glGetShaderiv &&
+ glGetShaderSource &&
+ glGetProgramiv &&
+ glGetProgramInfoLog &&
+ glGetUniformLocation &&
+ glUniform1fv &&
+ glUniform2fv &&
+ glUniform3fv &&
+ glUniform4fv &&
+ glUniform1i &&
+ glUniform1iv &&
+ glUniformMatrix2fv &&
+ glUniformMatrix3fv &&
+ glUniformMatrix4fv &&
+ glBindAttribLocation &&
+ glGetAttribLocation &&
+ glVertexAttrib1fv &&
+ glVertexAttrib2fv &&
+ glVertexAttrib3fv &&
+ glVertexAttrib4fv &&
+ glVertexAttribPointer &&
+ glDisableVertexAttribArray &&
+ glEnableVertexAttribArray;
+#endif
}
QT_END_NAMESPACE
diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
index a0517f5..f71ae9d 100644
--- a/src/opengl/qglextensions_p.h
+++ b/src/opengl/qglextensions_p.h
@@ -92,8 +92,10 @@ typedef void (APIENTRY *_glProgramLocalParameter4fvARB) (GLenum, GLuint, const G
// GLSL
typedef GLuint (APIENTRY *_glCreateShader) (GLenum);
typedef void (APIENTRY *_glShaderSource) (GLuint, GLsizei, const char **, const GLint *);
+typedef void (APIENTRY *_glShaderBinary) (GLint, const GLuint*, GLenum, const void*, GLint);
typedef void (APIENTRY *_glCompileShader) (GLuint);
typedef void (APIENTRY *_glDeleteShader) (GLuint);
+typedef GLboolean (APIENTRY *_glIsShader) (GLuint);
typedef GLuint (APIENTRY *_glCreateProgram) ();
typedef void (APIENTRY *_glAttachShader) (GLuint, GLuint);
@@ -101,17 +103,43 @@ typedef void (APIENTRY *_glDetachShader) (GLuint, GLuint);
typedef void (APIENTRY *_glLinkProgram) (GLuint);
typedef void (APIENTRY *_glUseProgram) (GLuint);
typedef void (APIENTRY *_glDeleteProgram) (GLuint);
+typedef GLboolean (APIENTRY *_glIsProgram) (GLuint);
typedef void (APIENTRY *_glGetShaderInfoLog) (GLuint, GLsizei, GLsizei *, char *);
typedef void (APIENTRY *_glGetShaderiv) (GLuint, GLenum, GLint *);
+typedef void (APIENTRY *_glGetShaderSource) (GLuint, GLsizei, GLsizei *, char *);
typedef void (APIENTRY *_glGetProgramiv) (GLuint, GLenum, GLint *);
+typedef void (APIENTRY *_glGetProgramInfoLog) (GLuint, GLsizei, GLsizei *, char *);
typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
-typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, GLfloat *);
+typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, const GLfloat *);
typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
+typedef void (APIENTRY *_glUniform1iv) (GLint, GLsizei, const GLint *);
+typedef void (APIENTRY *_glUniformMatrix2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix2x3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix2x4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix3x2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix3x4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix4x2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix4x3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+
+typedef void (APIENTRY *_glBindAttribLocation) (GLuint, GLuint, const char *);
+typedef GLint (APIENTRY *_glGetAttribLocation) (GLuint, const char *);
+typedef void (APIENTRY *_glVertexAttrib1fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttrib2fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttrib3fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttrib4fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttribPointer) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+typedef void (APIENTRY *_glDisableVertexAttribArray) (GLuint);
+typedef void (APIENTRY *_glEnableVertexAttribArray) (GLuint);
+
+typedef void (APIENTRY *_glGetProgramBinaryOES) (GLuint, GLsizei, GLsizei *, GLenum *, void *);
+typedef void (APIENTRY *_glProgramBinaryOES) (GLuint, GLenum, const void *, GLint);
typedef void (APIENTRY *_glActiveStencilFaceEXT) (GLenum );
@@ -153,10 +181,13 @@ struct QGLExtensionFuncs
qt_glGenProgramsARB = 0;
qt_glProgramLocalParameter4fvARB = 0;
+#if !defined(QT_OPENGL_ES_2)
qt_glCreateShader = 0;
qt_glShaderSource = 0;
+ qt_glShaderBinary = 0;
qt_glCompileShader = 0;
qt_glDeleteShader = 0;
+ qt_glIsShader = 0;
qt_glCreateProgram = 0;
qt_glAttachShader = 0;
@@ -164,10 +195,13 @@ struct QGLExtensionFuncs
qt_glLinkProgram = 0;
qt_glUseProgram = 0;
qt_glDeleteProgram = 0;
+ qt_glIsProgram = 0;
qt_glGetShaderInfoLog = 0;
qt_glGetShaderiv = 0;
+ qt_glGetShaderSource = 0;
qt_glGetProgramiv = 0;
+ qt_glGetProgramInfoLog = 0;
qt_glGetUniformLocation = 0;
qt_glUniform4fv = 0;
@@ -175,6 +209,32 @@ struct QGLExtensionFuncs
qt_glUniform2fv = 0;
qt_glUniform1fv = 0;
qt_glUniform1i = 0;
+ qt_glUniform1iv = 0;
+ qt_glUniformMatrix2fv = 0;
+ qt_glUniformMatrix3fv = 0;
+ qt_glUniformMatrix4fv = 0;
+ qt_glUniformMatrix2x3fv = 0;
+ qt_glUniformMatrix2x4fv = 0;
+ qt_glUniformMatrix3x2fv = 0;
+ qt_glUniformMatrix3x4fv = 0;
+ qt_glUniformMatrix4x2fv = 0;
+ qt_glUniformMatrix4x3fv = 0;
+
+ qt_glBindAttribLocation = 0;
+ qt_glGetAttribLocation = 0;
+ qt_glVertexAttrib1fv = 0;
+ qt_glVertexAttrib2fv = 0;
+ qt_glVertexAttrib3fv = 0;
+ qt_glVertexAttrib4fv = 0;
+ qt_glVertexAttribPointer = 0;
+ qt_glDisableVertexAttribArray = 0;
+ qt_glEnableVertexAttribArray = 0;
+#else
+ qt_glslResolved = false;
+
+ qt_glGetProgramBinaryOES = 0;
+ qt_glProgramBinaryOES = 0;
+#endif
qt_glActiveStencilFaceEXT = 0;
@@ -215,11 +275,14 @@ struct QGLExtensionFuncs
_glGenProgramsARB qt_glGenProgramsARB;
_glProgramLocalParameter4fvARB qt_glProgramLocalParameter4fvARB;
+#if !defined(QT_OPENGL_ES_2)
// GLSL definitions
_glCreateShader qt_glCreateShader;
_glShaderSource qt_glShaderSource;
+ _glShaderBinary qt_glShaderBinary;
_glCompileShader qt_glCompileShader;
_glDeleteShader qt_glDeleteShader;
+ _glIsShader qt_glIsShader;
_glCreateProgram qt_glCreateProgram;
_glAttachShader qt_glAttachShader;
@@ -227,10 +290,13 @@ struct QGLExtensionFuncs
_glLinkProgram qt_glLinkProgram;
_glUseProgram qt_glUseProgram;
_glDeleteProgram qt_glDeleteProgram;
+ _glIsProgram qt_glIsProgram;
_glGetShaderInfoLog qt_glGetShaderInfoLog;
_glGetShaderiv qt_glGetShaderiv;
+ _glGetShaderSource qt_glGetShaderSource;
_glGetProgramiv qt_glGetProgramiv;
+ _glGetProgramInfoLog qt_glGetProgramInfoLog;
_glGetUniformLocation qt_glGetUniformLocation;
_glUniform4fv qt_glUniform4fv;
@@ -238,6 +304,32 @@ struct QGLExtensionFuncs
_glUniform2fv qt_glUniform2fv;
_glUniform1fv qt_glUniform1fv;
_glUniform1i qt_glUniform1i;
+ _glUniform1iv qt_glUniform1iv;
+ _glUniformMatrix2fv qt_glUniformMatrix2fv;
+ _glUniformMatrix3fv qt_glUniformMatrix3fv;
+ _glUniformMatrix4fv qt_glUniformMatrix4fv;
+ _glUniformMatrix2x3fv qt_glUniformMatrix2x3fv;
+ _glUniformMatrix2x4fv qt_glUniformMatrix2x4fv;
+ _glUniformMatrix3x2fv qt_glUniformMatrix3x2fv;
+ _glUniformMatrix3x4fv qt_glUniformMatrix3x4fv;
+ _glUniformMatrix4x2fv qt_glUniformMatrix4x2fv;
+ _glUniformMatrix4x3fv qt_glUniformMatrix4x3fv;
+
+ _glBindAttribLocation qt_glBindAttribLocation;
+ _glGetAttribLocation qt_glGetAttribLocation;
+ _glVertexAttrib1fv qt_glVertexAttrib1fv;
+ _glVertexAttrib2fv qt_glVertexAttrib2fv;
+ _glVertexAttrib3fv qt_glVertexAttrib3fv;
+ _glVertexAttrib4fv qt_glVertexAttrib4fv;
+ _glVertexAttribPointer qt_glVertexAttribPointer;
+ _glDisableVertexAttribArray qt_glDisableVertexAttribArray;
+ _glEnableVertexAttribArray qt_glEnableVertexAttribArray;
+#else
+ bool qt_glslResolved;
+
+ _glGetProgramBinaryOES qt_glGetProgramBinaryOES;
+ _glProgramBinaryOES qt_glProgramBinaryOES;
+#endif
_glActiveStencilFaceEXT qt_glActiveStencilFaceEXT;
@@ -479,10 +571,14 @@ struct QGLExtensionFuncs
#define glMapBufferARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glMapBufferARB
#define glUnmapBufferARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUnmapBufferARB
+#if !defined(QT_OPENGL_ES_2)
+
#define glCreateShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCreateShader
#define glShaderSource QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glShaderSource
+#define glShaderBinary QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glShaderBinary
#define glCompileShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCompileShader
#define glDeleteShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteShader
+#define glIsShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsShader
#define glCreateProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCreateProgram
#define glAttachShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glAttachShader
@@ -490,10 +586,13 @@ struct QGLExtensionFuncs
#define glLinkProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glLinkProgram
#define glUseProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUseProgram
#define glDeleteProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteProgram
+#define glIsProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsProgram
#define glGetShaderInfoLog QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderInfoLog
#define glGetShaderiv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderiv
+#define glGetShaderSource QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderSource
#define glGetProgramiv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramiv
+#define glGetProgramInfoLog QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramInfoLog
#define glGetUniformLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetUniformLocation
#define glUniform4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform4fv
@@ -501,6 +600,33 @@ struct QGLExtensionFuncs
#define glUniform2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform2fv
#define glUniform1fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1fv
#define glUniform1i QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1i
+#define glUniform1iv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1iv
+#define glUniformMatrix2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2fv
+#define glUniformMatrix3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3fv
+#define glUniformMatrix4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4fv
+#define glUniformMatrix2x3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2x3fv
+#define glUniformMatrix2x4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2x4fv
+#define glUniformMatrix3x2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3x2fv
+#define glUniformMatrix3x4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3x4fv
+#define glUniformMatrix4x2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4x2fv
+#define glUniformMatrix4x3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4x3fv
+
+#define glBindAttribLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindAttribLocation
+#define glGetAttribLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetAttribLocation
+#define glVertexAttrib1fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib1fv
+#define glVertexAttrib2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib2fv
+#define glVertexAttrib3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib3fv
+#define glVertexAttrib4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib4fv
+#define glVertexAttribPointer QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttribPointer
+#define glDisableVertexAttribArray QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDisableVertexAttribArray
+#define glEnableVertexAttribArray QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glEnableVertexAttribArray
+
+#else // QT_OPENGL_ES_2
+
+#define glGetProgramBinaryOES QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramBinaryOES
+#define glProgramBinaryOES QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glProgramBinaryOES
+
+#endif // QT_OPENGL_ES_2
extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx);
bool qt_resolve_buffer_extensions(QGLContext *ctx);
diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp
index ff23948..0bfed12 100644
--- a/src/opengl/qglpixmapfilter.cpp
+++ b/src/opengl/qglpixmapfilter.cpp
@@ -45,27 +45,12 @@
#include "qpaintengine_opengl_p.h"
#include "qglpixelbuffer.h"
-#include "qglextensions_p.h"
+#include "qglshaderprogram.h"
#include "qgl_p.h"
#include "private/qapplication_p.h"
-#ifndef GL_FRAGMENT_SHADER
-#define GL_FRAGMENT_SHADER 0x8B30
-#endif
-
-#ifndef GL_COMPILE_STATUS
-#define GL_COMPILE_STATUS 0x8B81
-#endif
-
-#ifndef GL_LINK_STATUS
-#define GL_LINK_STATUS 0x8B82
-#endif
-
-
-
-
QT_BEGIN_NAMESPACE
@@ -79,117 +64,6 @@ void QGLPixmapFilterBase::drawImpl(QPainter *painter, const QPointF &pos, const
processGL(painter, pos, src, source);
}
-QGLSLProgram::QGLSLProgram(const QString &src)
- : ctx(QGLContext::currentContext())
-{
- if (!qt_resolve_glsl_extensions(const_cast<QGLContext *>(ctx))) {
- qWarning("Failed to resolve GLSL functions");
- m_valid = false;
- return;
- }
-
- m_shader = glCreateShader(GL_FRAGMENT_SHADER);
-
- const QByteArray src_ba = src.toAscii();
- const char *src_cstr = src_ba.constData();
-
- glShaderSource(m_shader, 1, &src_cstr, 0);
- glCompileShader(m_shader);
- glGetShaderiv(m_shader, GL_COMPILE_STATUS, &m_valid);
- if (!m_valid) {
- char data[4096];
- GLsizei len;
- glGetShaderInfoLog(m_shader, 4096, &len, data);
- qWarning("Failed to compile GLSL shader:\n%s\nCODE:\n%s\n", data, src_cstr);
- return;
- }
-
- m_program = glCreateProgram();
- glAttachShader(m_program, m_shader);
- glLinkProgram(m_program);
- glGetProgramiv(m_program, GL_LINK_STATUS, &m_valid);
- if (!m_valid) {
- char data[4096];
- GLsizei len;
- glGetShaderInfoLog(m_shader, 4096, &len, data);
- qWarning("Failed to link GLSL program:\n%s\nCODE:\n%s\n", data, src_cstr);
- return;
- }
-}
-
-QGLSLProgram::~QGLSLProgram()
-{
- glDeleteProgram(m_program);
- glDeleteShader(m_shader);
-}
-
-bool QGLSLProgram::success() const
-{
- return m_valid;
-}
-
-void QGLSLProgram::enable()
-{
- glUseProgram(m_program);
-}
-
-void QGLSLProgram::disable()
-{
- glUseProgram(0);
-}
-
-typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
-typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
-
-int QGLSLProgram::getUniformLocation(const QString &name)
-{
- return glGetUniformLocation(m_program, name.toAscii().constData());
-}
-
-void QGLSLProgram::setUniform(int uniform, int value)
-{
- enable();
- glUniform1i(uniform, value);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal value)
-{
- enable();
- GLfloat v[] = { value };
- glUniform1fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2)
-{
- enable();
- GLfloat v[] = { v1, v2 };
- glUniform2fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2, qreal v3)
-{
- enable();
- GLfloat v[] = { v1, v2, v3 };
- glUniform3fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2, qreal v3, qreal v4)
-{
- enable();
- GLfloat v[] = { v1, v2, v3, v4 };
- glUniform4fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, int count, float *v)
-{
- enable();
- glUniform1fv(uniform, count, v);
-}
-
class QGLPixmapColorizeFilter: public QGLPixmapFilter<QPixmapColorizeFilter>
{
public:
@@ -199,8 +73,8 @@ protected:
bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &pixmap, const QRectF &srcRect) const;
private:
- mutable QGLSLProgram m_program;
- uint m_colorUniform;
+ mutable QGLShaderProgram m_program;
+ int m_colorUniform;
};
class QGLPixmapConvolutionFilter: public QGLPixmapFilter<QPixmapConvolutionFilter>
@@ -213,11 +87,11 @@ protected:
bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const;
private:
- QString generateConvolutionShader() const;
+ QByteArray generateConvolutionShader() const;
- mutable QGLSLProgram *m_program;
- mutable uint m_scaleUniform;
- mutable uint m_matrixUniform;
+ mutable QGLShaderProgram *m_program;
+ mutable int m_scaleUniform;
+ mutable int m_matrixUniform;
mutable int m_kernelWidth;
mutable int m_kernelHeight;
@@ -294,10 +168,12 @@ static const char *qt_gl_colorize_filter =
"}";
QGLPixmapColorizeFilter::QGLPixmapColorizeFilter()
- : m_program(QLatin1String(qt_gl_colorize_filter))
{
- m_program.setUniform(m_program.getUniformLocation(QLatin1String("texture")), 0); // GL_TEXTURE_0
- m_colorUniform = m_program.getUniformLocation(QLatin1String("color"));
+ m_program.addShader(QGLShader::FragmentShader, qt_gl_colorize_filter);
+ m_program.link();
+ m_program.enable();
+ m_program.setUniformValue(m_program.uniformLocation("texture"),GLint(0)); // GL_TEXTURE_0
+ m_colorUniform = m_program.uniformLocation("color");
}
bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const
@@ -305,10 +181,10 @@ bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QP
bindTexture(src);
QColor col = color();
- m_program.setUniform(m_colorUniform, col.redF(), col.greenF(), col.blueF());
+ m_program.enable();
+ m_program.setUniformValue(m_colorUniform, col.redF(), col.greenF(), col.blueF());
QRectF target = (srcRect.isNull() ? QRectF(src.rect()) : srcRect).translated(pos);
- m_program.enable();
qgl_drawTexture(target, src.width(), src.height(), srcRect);
m_program.disable();
@@ -316,7 +192,7 @@ bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QP
}
// generates convolution filter code for arbitrary sized kernel
-QString QGLPixmapConvolutionFilter::generateConvolutionShader() const {
+QByteArray QGLPixmapConvolutionFilter::generateConvolutionShader() const {
QByteArray code;
code.append("uniform sampler2D texture;\n");
code.append("uniform vec2 inv_texture_size;\n");
@@ -352,7 +228,7 @@ QString QGLPixmapConvolutionFilter::generateConvolutionShader() const {
code.append(" }\n");
code.append(" gl_FragColor = sum;\n");
code.append("}");
- return QLatin1String(code);
+ return code;
}
QGLPixmapConvolutionFilter::QGLPixmapConvolutionFilter()
@@ -384,10 +260,12 @@ bool QGLPixmapConvolutionFilter::processGL(QPainter *, const QPointF &pos, const
m_kernelWidth = columns();
m_kernelHeight = rows();
- QString code = generateConvolutionShader();
- m_program = new QGLSLProgram(code);
- m_scaleUniform = m_program->getUniformLocation(QLatin1String("inv_texture_size"));
- m_matrixUniform = m_program->getUniformLocation(QLatin1String("matrix"));
+ QByteArray code = generateConvolutionShader();
+ m_program = new QGLShaderProgram();
+ m_program->addShader(QGLShader::FragmentShader, code);
+ m_program->link();
+ m_scaleUniform = m_program->uniformLocation("inv_texture_size");
+ m_matrixUniform = m_program->uniformLocation("matrix");
}
const qreal *kernel = convolutionKernel();
@@ -397,10 +275,10 @@ bool QGLPixmapConvolutionFilter::processGL(QPainter *, const QPointF &pos, const
const qreal iw = 1.0 / src.width();
const qreal ih = 1.0 / src.height();
- m_program->setUniform(m_scaleUniform, iw, ih);
- m_program->setUniform(m_matrixUniform, m_kernelWidth * m_kernelHeight, conv);
-
m_program->enable();
+ m_program->setUniformValue(m_scaleUniform, iw, ih);
+ m_program->setUniformValueArray(m_matrixUniform, conv, m_kernelWidth * m_kernelHeight, 1);
+
qgl_drawTexture(target, src.width(), src.height(), boundingRectFor(srcRect));
m_program->disable();
return true;
diff --git a/src/opengl/qglpixmapfilter_p.h b/src/opengl/qglpixmapfilter_p.h
index dc2eea6..d6742fc 100644
--- a/src/opengl/qglpixmapfilter_p.h
+++ b/src/opengl/qglpixmapfilter_p.h
@@ -87,35 +87,6 @@ public:
}
};
-class Q_OPENGL_EXPORT QGLSLProgram
-{
-public:
- QGLSLProgram(const QString &src);
- ~QGLSLProgram();
-
- bool success() const;
-
- void enable();
- void disable();
-
- int getUniformLocation(const QString &name);
-
- void setUniform(int uniform, int value);
- void setUniform(int uniform, qreal value);
- void setUniform(int uniform, qreal v1, qreal v2);
- void setUniform(int uniform, qreal v1, qreal v2, qreal v3);
- void setUniform(int uniform, qreal v1, qreal v2, qreal v3, qreal v4);
- void setUniform(int uniform, int count, float *v);
-
-private:
- GLuint m_shader;
- GLuint m_program;
-
- GLint m_valid;
-
- const QGLContext *ctx;
-};
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
new file mode 100644
index 0000000..d74b930
--- /dev/null
+++ b/src/opengl/qglshaderprogram.cpp
@@ -0,0 +1,2992 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglshaderprogram.h"
+#include "qglextensions_p.h"
+#include "qgl_p.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+
+/*!
+ \class QGLShaderProgram
+ \brief The QGLShaderProgram class allows OpenGL shader programs to be linked and used.
+ \since 4.6
+
+ \section1 Introduction
+
+ This class supports shader programs written in the OpenGL Shading
+ Language (GLSL) and in the OpenGL/ES Shading Language (GLSL/ES).
+
+ QGLShader and QGLShaderProgram shelter the programmer from the details of
+ compiling and linking vertex and fragment shaders.
+
+ The following example creates a vertex shader program using the
+ supplied source \c{code}. Once compiled and linked, the shader
+ program is activated in the current QGLContext by calling
+ QGLShaderProgram::enable():
+
+ \code
+ QGLShader shader(QGLShader::VertexShader);
+ shader.setSourceCode(code);
+
+ QGLShaderProgram program(context);
+ program.addShader(shader);
+ program.link();
+
+ program.enable();
+ \endcode
+
+ \section1 Writing portable shaders
+
+ Shader programs can be difficult to reuse across OpenGL implementations
+ because of varying levels of support for standard vertex attributes and
+ uniform variables. In particular, GLSL/ES lacks all of the
+ standard variables that are present on desktop OpenGL systems:
+ \c{gl_Vertex}, \c{gl_Normal}, \c{gl_Color}, and so on. Desktop OpenGL
+ lacks the variable qualifiers \c{highp}, \c{mediump}, and \c{lowp}.
+
+ The QGLShaderProgram class makes the process of writing portable shaders
+ easier by prefixing all shader programs with the following lines on
+ desktop OpenGL:
+
+ \code
+ #define highp
+ #define mediump
+ #define lowp
+ \endcode
+
+ This makes it possible to run most GLSL/ES shader programs
+ on desktop systems. The programmer should restrict themselves
+ to just features that are present in GLSL/ES, and avoid
+ standard variable names that only work on the desktop.
+
+ \section1 Simple shader example
+
+ \code
+ program.addShader(QGLShader::VertexShader,
+ "attribute highp vec4 vertex;\n"
+ "attribute mediump mat4 matrix;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = matrix * vertex;\n"
+ "}");
+ program.addShader(QGLShader::FragmentShader,
+ "uniform mediump vec4 color;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_FragColor = color;\n"
+ "}");
+ program.link();
+ program.enable();
+
+ int vertexLocation = program.attributeLocation("vertex");
+ int matrixLocation = program.attributeLocation("matrix");
+ int colorLocation = program.uniformLocation("color");
+ \endcode
+
+ With the above shader program active, we can draw a green triangle
+ as follows:
+
+ \code
+ static GLfloat const triangleVertices[] = {
+ 60.0f, 10.0f, 0.0f,
+ 110.0f, 110.0f, 0.0f,
+ 10.0f, 110.0f, 0.0f
+ };
+
+ QColor color(0, 255, 0, 255);
+
+ QMatrix4x4 pmvMatrix;
+ pmvMatrix.ortho(rect());
+
+ program.setAttributeArray(vertexLocation, triangleVertices, 3);
+ program.setUniformValue(matrixLocation, pmvMatrix);
+ program.setUniformValue(colorLocation, color);
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ \endcode
+
+ \section1 Partial shaders
+
+ Desktop GLSL can attach an arbitrary number of vertex and fragment
+ shaders to a shader program. Embedded GLSL/ES on the other hand
+ supports only a single shader of each type on a shader program.
+
+ Multiple shaders of the same type can be useful when large libraries
+ of shaders are needed. Common functions can be factored out into
+ library shaders that can be reused in multiple shader programs.
+
+ To support this use of shaders, the application programmer can
+ create shaders with the QGLShader::PartialVertexShader and
+ QGLShader::PartialFragmentShader types. These types direct
+ QGLShader and QGLShaderProgram to delay shader compilation until
+ link time.
+
+ When link() is called, the sources for the partial shaders are
+ concatenated, and a single vertex or fragment shader is compiled
+ and linked into the shader program.
+
+ It is more efficient to use the QGLShader::VertexShader and
+ QGLShader::FragmentShader when there is only one shader of that
+ type in the program.
+
+ \sa QGLShader
+*/
+
+/*!
+ \class QGLShader
+ \brief The QGLShader class allows OpenGL shaders to be compiled.
+ \since 4.6
+
+ This class supports shaders written in the OpenGL Shading Language (GLSL)
+ and in the OpenGL/ES Shading Language (GLSL/ES).
+
+ QGLShader and QGLShaderProgram shelter the programmer from the details of
+ compiling and linking vertex and fragment shaders.
+
+ \sa QGLShaderProgram
+*/
+
+/*!
+ \enum QGLShader::ShaderType
+ This enum specifies the type of QGLShader that is being created.
+
+ \value VertexShader Vertex shader written in the OpenGL Shading Language (GLSL).
+ \value FragmentShader Fragment shader written in the OpenGL Shading Language (GLSL).
+ \value PartialVertexShader Partial vertex shader that will be concatenated with all other partial vertex shaders at link time.
+ \value PartialFragmentShader Partial fragment shader that will be concatenated with all other partial fragment shaders at link time.
+*/
+
+#ifndef GL_FRAGMENT_SHADER
+#define GL_FRAGMENT_SHADER 0x8B30
+#endif
+#ifndef GL_VERTEX_SHADER
+#define GL_VERTEX_SHADER 0x8B31
+#endif
+#ifndef GL_COMPILE_STATUS
+#define GL_COMPILE_STATUS 0x8B81
+#endif
+#ifndef GL_LINK_STATUS
+#define GL_LINK_STATUS 0x8B82
+#endif
+#ifndef GL_INFO_LOG_LENGTH
+#define GL_INFO_LOG_LENGTH 0x8B84
+#endif
+#ifndef GL_ACTIVE_UNIFORMS
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#endif
+#ifndef GL_ACTIVE_UNIFORM_MAX_LENGTH
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#endif
+#ifndef GL_ACTIVE_ATTRIBUTES
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#endif
+#ifndef GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#endif
+#ifndef GL_CURRENT_VERTEX_ATTRIB
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#endif
+#ifndef GL_SHADER_SOURCE_LENGTH
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#endif
+#ifndef GL_SHADER_BINARY_FORMATS
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#endif
+#ifndef GL_NUM_SHADER_BINARY_FORMATS
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#endif
+
+class QGLShaderPrivate
+{
+public:
+ QGLShaderPrivate(QGLShader::ShaderType type, const QGLContext *ctx)
+ {
+ context = ctx;
+ shader = 0;
+ shaderType = type;
+ compiled = false;
+ isPartial = (type == QGLShader::PartialVertexShader ||
+ type == QGLShader::PartialFragmentShader);
+ hasPartialSource = false;
+ }
+
+ const QGLContext *context;
+ GLuint shader;
+ QGLShader::ShaderType shaderType;
+ bool compiled;
+ bool isPartial;
+ bool hasPartialSource;
+ QString log;
+ QByteArray partialSource;
+
+ bool create();
+ bool compile();
+};
+
+#define ctx context
+
+bool QGLShaderPrivate::create()
+{
+ if (isPartial)
+ return true;
+ if (!context)
+ context = QGLContext::currentContext();
+ if (!context)
+ return false;
+ if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(context))) {
+ if (shaderType == QGLShader::VertexShader)
+ shader = glCreateShader(GL_VERTEX_SHADER);
+ else
+ shader = glCreateShader(GL_FRAGMENT_SHADER);
+ if (!shader) {
+ qWarning() << "QGLShader: could not create shader";
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QGLShaderPrivate::compile()
+{
+ // Partial shaders are compiled during QGLShaderProgram::link().
+ if (isPartial && hasPartialSource) {
+ compiled = true;
+ return true;
+ }
+ if (!shader)
+ return false;
+ glCompileShader(shader);
+ GLint value = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
+ compiled = (value != 0);
+ value = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &value);
+ if (!compiled && value > 1) {
+ char *logbuf = new char [value];
+ GLint len;
+ glGetShaderInfoLog(shader, value, &len, logbuf);
+ log = QString::fromLatin1(logbuf);
+ qWarning() << "QGLShader::compile:" << log;
+ delete [] logbuf;
+ }
+ return compiled;
+}
+
+#undef ctx
+#define ctx d->context
+
+/*!
+ Constructs a new QGLShader object of the specified \a type
+ and attaches it to \a parent. If shader programs are not supported,
+ then isValid() will return false.
+
+ This constructor is normally followed by a call to setSourceCode()
+ or setSourceCodeFile().
+
+ The shader will be associated with the current QGLContext.
+
+ \sa setSourceCode(), setSourceCodeFile(), isValid()
+*/
+QGLShader::QGLShader(QGLShader::ShaderType type, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, QGLContext::currentContext());
+ d->create();
+}
+
+/*!
+ Constructs a new QGLShader object from the source code in \a fileName
+ and attaches it to \a parent. If the filename ends in \c{.fsh},
+ it is assumed to be a fragment shader, otherwise it is assumed to
+ be a vertex shader (normally the extension is \c{.vsh} for vertex shaders).
+ If the shader could not be loaded, then isValid() will return false.
+
+ The shader will be associated with the current QGLContext.
+
+ \sa isValid()
+*/
+QGLShader::QGLShader(const QString& fileName, QObject *parent)
+ : QObject(parent)
+{
+ if (fileName.endsWith(QLatin1String(".fsh"), Qt::CaseInsensitive))
+ d = new QGLShaderPrivate(QGLShader::FragmentShader, QGLContext::currentContext());
+ else
+ d = new QGLShaderPrivate(QGLShader::VertexShader, QGLContext::currentContext());
+ if (d->create() && !setSourceCodeFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Constructs a new QGLShader object of the specified \a type from the
+ source code in \a fileName and attaches it to \a parent.
+ If the shader could not be loaded, then isValid() will return false.
+
+ The shader will be associated with the current QGLContext.
+
+ \sa isValid()
+*/
+QGLShader::QGLShader
+ (const QString& fileName, QGLShader::ShaderType type, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, QGLContext::currentContext());
+ if (d->create() && !setSourceCodeFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Constructs a new QGLShader object of the specified \a type
+ and attaches it to \a parent. If shader programs are not supported,
+ then isValid() will return false.
+
+ This constructor is normally followed by a call to setSourceCode()
+ or setSourceCodeFile().
+
+ The shader will be associated with \a context.
+
+ \sa setSourceCode(), setSourceCodeFile(), isValid()
+*/
+QGLShader::QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, context);
+ d->create();
+}
+
+/*!
+ Constructs a new QGLShader object from the source code in \a fileName
+ and attaches it to \a parent. If the filename ends in \c{.fsh},
+ it is assumed to be a fragment shader, otherwise it is assumed to
+ be a vertex shader (normally the extension is \c{.vsh} for vertex shaders).
+ If the shader could not be loaded, then isValid() will return false.
+
+ The shader will be associated with \a context.
+
+ \sa isValid()
+*/
+QGLShader::QGLShader(const QString& fileName, const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ if (fileName.endsWith(QLatin1String(".fsh"), Qt::CaseInsensitive))
+ d = new QGLShaderPrivate(QGLShader::FragmentShader, context);
+ else
+ d = new QGLShaderPrivate(QGLShader::VertexShader, context);
+ if (d->create() && !setSourceCodeFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Constructs a new QGLShader object of the specified \a type from the
+ source code in \a fileName and attaches it to \a parent.
+ If the shader could not be loaded, then isValid() will return false.
+
+ The shader will be associated with \a context.
+
+ \sa isValid()
+*/
+QGLShader::QGLShader
+ (const QString& fileName, QGLShader::ShaderType type, const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, context);
+ if (d->create() && !setSourceCodeFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Deletes this shader. If the shader has been attached to a
+ QGLShaderProgram object, then the actual shader will stay around
+ until the QGLShaderProgram is destroyed.
+*/
+QGLShader::~QGLShader()
+{
+ if (d->shader)
+ glDeleteShader(d->shader);
+ delete d;
+}
+
+/*!
+ Returns true if this shader is valid. Shaders become invalid
+ when they are destroyed and no longer attached to a QGLShaderProgram.
+*/
+bool QGLShader::isValid() const
+{
+ if (d->isPartial && d->hasPartialSource)
+ return true;
+ if (!d->shader)
+ return false;
+#if defined(QT_OPENGL_ES_2)
+ return glIsShader(d->shader);
+#else
+ // glIsShader() may not exist on some systems.
+ return (!glIsShader || glIsShader(d->shader));
+#endif
+}
+
+/*!
+ Returns the type of this shader.
+*/
+QGLShader::ShaderType QGLShader::shaderType() const
+{
+ return d->shaderType;
+}
+
+// The precision qualifiers are useful on OpenGL/ES systems,
+// but usually not present on desktop systems. Define the
+// keywords to empty strings on desktop systems.
+#ifndef QT_OPENGL_ES
+#define QGL_DEFINE_QUALIFIERS 1
+static const char qualifierDefines[] =
+ "#define lowp\n"
+ "#define mediump\n"
+ "#define highp\n";
+#endif
+
+/*!
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+*/
+bool QGLShader::setSourceCode(const char *source)
+{
+ if (d->isPartial) {
+ d->partialSource = QByteArray(source);
+ d->hasPartialSource = true;
+ return d->compile();
+ } else if (d->shader) {
+ QVarLengthArray<const char *> src;
+#ifdef QGL_DEFINE_QUALIFIERS
+ src.append(qualifierDefines);
+#endif
+ src.append(source);
+ glShaderSource(d->shader, src.size(), src.data(), 0);
+ return d->compile();
+ } else {
+ return false;
+ }
+}
+
+/*!
+ \overload
+
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+*/
+bool QGLShader::setSourceCode(const QByteArray& source)
+{
+ return setSourceCode(source.constData());
+}
+
+/*!
+ \overload
+
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+*/
+bool QGLShader::setSourceCode(const QString& source)
+{
+ return setSourceCode(source.toLatin1().constData());
+}
+
+/*!
+ Sets the source code for this shader to the contents of \a fileName
+ and compiles it. Returns true if the file could be opened and the
+ source compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+*/
+bool QGLShader::setSourceCodeFile(const QString& fileName)
+{
+ QFile file(fileName);
+ if (!file.open(QFile::ReadOnly)) {
+ qWarning() << "QGLShader: Unable to open file" << fileName;
+ return false;
+ }
+
+ QByteArray contents = file.readAll();
+ return setSourceCode(contents.constData());
+}
+
+/*!
+ Sets the binary code for this shader to the \a length bytes from
+ the array \a binary. The \a format specifies how the binary data
+ should be interpreted by the OpenGL engine. Returns true if the
+ binary was set on the shader; false otherwise.
+
+ This function cannot be used with PartialVertexShader or
+ PartialFragmentShader.
+
+ \sa shaderBinaryFormats()
+*/
+bool QGLShader::setBinaryCode(GLenum format, const void *binary, int length)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!glShaderBinary)
+ return false;
+#endif
+ if (d->isPartial || !d->shader)
+ return false;
+ glGetError(); // Clear error state.
+ glShaderBinary(1, &(d->shader), format, binary, length);
+ return (glGetError() == GL_NO_ERROR);
+}
+
+/*!
+ Sets the binary code for this shader to the \a length bytes from
+ the array \a binary. The \a format specifies how the binary data
+ should be interpreted by the OpenGL engine. Returns true if the
+ binary was set on the shader; false otherwise.
+
+ The \a otherShader will also have binary code set on it. This is
+ for the case where \a binary contains both vertex and fragment
+ shader code.
+
+ This function cannot be used with PartialVertexShader or
+ PartialFragmentShader.
+
+ \sa shaderBinaryFormats()
+*/
+bool QGLShader::setBinaryCode
+ (QGLShader& otherShader, GLenum format, const void *binary, int length)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!glShaderBinary)
+ return false;
+#endif
+ if (d->isPartial || !d->shader)
+ return false;
+ if (otherShader.d->isPartial || !otherShader.d->shader)
+ return false;
+ glGetError(); // Clear error state.
+ GLuint shaders[2];
+ shaders[0] = d->shader;
+ shaders[1] = otherShader.d->shader;
+ glShaderBinary(2, shaders, format, binary, length);
+ return (glGetError() == GL_NO_ERROR);
+}
+
+/*!
+ Returns a list of all binary formats that are supported by
+ setBinaryCode() on this system.
+
+ \sa setBinaryCode()
+*/
+QList<GLenum> QGLShader::shaderBinaryFormats()
+{
+ GLint num;
+ QList<GLenum> list;
+ glGetError(); // Clear error state.
+ glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &num);
+ if (glGetError() != GL_NO_ERROR || num <= 0)
+ return list;
+ QVarLengthArray<GLint> formats(num);
+ glGetIntegerv(GL_SHADER_BINARY_FORMATS, formats.data());
+ for (GLint i = 0; i < num; ++i)
+ list += (GLenum)(formats[i]);
+ return list;
+}
+
+/*!
+ Returns the source code for this shader.
+
+ \sa setSourceCode()
+*/
+QByteArray QGLShader::sourceCode() const
+{
+ if (d->isPartial)
+ return d->partialSource;
+ if (!d->shader)
+ return QByteArray();
+ GLint size = 0;
+ glGetShaderiv(d->shader, GL_SHADER_SOURCE_LENGTH, &size);
+ if (size <= 0)
+ return QByteArray();
+ GLint len = 0;
+ char *source = new char [size];
+ glGetShaderSource(d->shader, size, &len, source);
+ QByteArray src(source);
+ delete [] source;
+ return src;
+}
+
+/*!
+ Returns true if this shader has been compiled; false otherwise.
+
+ \sa setSourceCode()
+*/
+bool QGLShader::isCompiled() const
+{
+ return d->compiled;
+}
+
+/*!
+ Returns the errors and warnings that occurred during the last compile.
+
+ \sa setSourceCode()
+*/
+QString QGLShader::log() const
+{
+ return d->log;
+}
+
+/*!
+ Returns the OpenGL identifier associated with this shader.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ this function will always return zero. Partial shaders are
+ created and compiled when QGLShaderProgram::link() is called.
+
+ \sa QGLShaderProgram::programId()
+*/
+GLuint QGLShader::shaderId() const
+{
+ return d->shader;
+}
+
+#undef ctx
+#define ctx context
+
+class QGLShaderProgramPrivate
+{
+public:
+ QGLShaderProgramPrivate(const QGLContext *ctx)
+ {
+ context = ctx;
+ program = 0;
+ linked = false;
+ inited = false;
+ hasPartialShaders = false;
+ vertexShader = 0;
+ fragmentShader = 0;
+ }
+ ~QGLShaderProgramPrivate()
+ {
+ if (program)
+ glDeleteProgram(program);
+ }
+
+ const QGLContext *context;
+ GLuint program;
+ bool linked;
+ bool inited;
+ bool hasPartialShaders;
+ QString log;
+ QList<QGLShader *> shaders;
+ QList<QGLShader *> anonShaders;
+ QGLShader *vertexShader;
+ QGLShader *fragmentShader;
+};
+
+#undef ctx
+#define ctx d->context
+
+/*!
+ Constructs a new shader program and attaches it to \a parent.
+ The program will be invalid until addShader() is called.
+
+ The shader program will be associated with the current QGLContext.
+
+ \sa isValid(), addShader()
+*/
+QGLShaderProgram::QGLShaderProgram(QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderProgramPrivate(QGLContext::currentContext());
+}
+
+/*!
+ Constructs a new shader program and attaches it to \a parent.
+ The program will be invalid until addShader() is called.
+
+ The shader program will be associated with \a context.
+
+ \sa isValid(), addShader()
+*/
+QGLShaderProgram::QGLShaderProgram(const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderProgramPrivate(context);
+}
+
+/*!
+ Deletes this shader program.
+*/
+QGLShaderProgram::~QGLShaderProgram()
+{
+ delete d;
+}
+
+bool QGLShaderProgram::init()
+{
+ if (d->program || d->inited)
+ return true;
+ d->inited = true;
+ if (!d->context)
+ d->context = QGLContext::currentContext();
+ if (!d->context)
+ return false;
+ if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(d->context))) {
+ d->program = glCreateProgram();
+ if (!(d->program)) {
+ qWarning() << "QGLShaderProgram: could not create shader program";
+ return false;
+ }
+ return true;
+ } else {
+ qWarning() << "QGLShaderProgram: shader programs are not supported";
+ return false;
+ }
+}
+
+/*!
+ Returns true if this shader program object is valid, false otherwise.
+*/
+bool QGLShaderProgram::isValid() const
+{
+ if (!d->program)
+ return false;
+#if defined(QT_OPENGL_ES_2)
+ return glIsProgram(d->program);
+#else
+ // glIsProgram() may not exist on some systems.
+ return (!glIsProgram || glIsProgram(d->program));
+#endif
+}
+
+/*!
+ Adds a compiled \a shader to this shader program. Returns true
+ if the shader could be added, or false otherwise.
+
+ Ownership of the \a shader object remains with the caller.
+ It will not be deleted when this QGLShaderProgram instance
+ is deleted. This allows the caller to add the same shader
+ to multiple shader programs.
+
+ \sa removeShader(), link(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader *shader)
+{
+ if (!init())
+ return false;
+ if (d->shaders.contains(shader))
+ return true; // Already added to this shader program.
+ if (d->program && shader) {
+ if (!shader->d->compiled)
+ return false;
+ if (!shader->d->isPartial) {
+ if (!shader->d->shader)
+ return false;
+ glAttachShader(d->program, shader->d->shader);
+ } else {
+ d->hasPartialShaders = true;
+ }
+ d->linked = false; // Program needs to be relinked.
+ d->shaders.append(shader);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Compiles \a source as a shader of the specified \a type and
+ adds it to this shader program. Returns true if compilation
+ was successful, false otherwise. The compilation errors
+ and warnings will be made available via log().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa removeShader(), link(), log(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const char *source)
+{
+ if (!init())
+ return false;
+ QGLShader *shader = new QGLShader(type, this);
+ if (!shader->setSourceCode(source)) {
+ d->log = shader->log();
+ delete shader;
+ return false;
+ }
+ d->anonShaders.append(shader);
+ return addShader(shader);
+}
+
+/*!
+ \overload
+
+ Compiles \a source as a shader of the specified \a type and
+ adds it to this shader program. Returns true if compilation
+ was successful, false otherwise. The compilation errors
+ and warnings will be made available via log().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa removeShader(), link(), log(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const QByteArray& source)
+{
+ return addShader(type, source.constData());
+}
+
+/*!
+ \overload
+
+ Compiles \a source as a shader of the specified \a type and
+ adds it to this shader program. Returns true if compilation
+ was successful, false otherwise. The compilation errors
+ and warnings will be made available via log().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa removeShader(), link(), log(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const QString& source)
+{
+ return addShader(type, source.toLatin1().constData());
+}
+
+/*!
+ Removes \a shader from this shader program. The object is not deleted.
+
+ \sa addShader(), link(), removeAllShaders()
+*/
+void QGLShaderProgram::removeShader(QGLShader *shader)
+{
+ if (d->program && shader && shader->d->shader) {
+ glDetachShader(d->program, shader->d->shader);
+ d->linked = false; // Program needs to be relinked.
+ }
+ d->shaders.removeAll(shader);
+ d->anonShaders.removeAll(shader);
+}
+
+/*!
+ Returns a list of all shaders that have been added to this shader
+ program using addShader().
+
+ \sa addShader(), removeShader()
+*/
+QList<QGLShader *> QGLShaderProgram::shaders() const
+{
+ return d->shaders;
+}
+
+/*!
+ Removes all of the shaders that were added to this program previously.
+ The QGLShader objects for the shaders will not be deleted if they
+ were constructed externally. QGLShader objects that are constructed
+ internally by QGLShaderProgram will be deleted.
+
+ \sa addShader(), removeShader()
+*/
+void QGLShaderProgram::removeAllShaders()
+{
+ foreach (QGLShader *shader, d->shaders) {
+ if (d->program && shader && shader->d->shader)
+ glDetachShader(d->program, shader->d->shader);
+ }
+ foreach (QGLShader *shader, d->anonShaders) {
+ // Delete shader objects that were created anonymously.
+ delete shader;
+ }
+ d->shaders.clear();
+ d->anonShaders.clear();
+ d->linked = false; // Program needs to be relinked.
+}
+
+#if defined(QT_OPENGL_ES_2)
+
+#ifndef GL_PROGRAM_BINARY_LENGTH_OES
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#endif
+#ifndef GL_NUM_PROGRAM_BINARY_FORMATS_OES
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#endif
+#ifndef GL_PROGRAM_BINARY_FORMATS_OES
+#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+#endif
+
+#endif
+
+/*!
+ Returns the program binary associated with this shader program.
+ The numeric identifier of the program binary format is returned
+ in \a format. The \c OES_get_program_binary extension will need
+ to be supported by the system for binary retrieval to succeed.
+
+ Returns an empty QByteArray if the program binary cannot be
+ retrieved on this system, or the shader program has not yet
+ been linked.
+
+ The returned binary can be supplied to setProgramBinary() on the
+ same machine at some future point to reload the program. It contains
+ the compiled code of all of the shaders that were attached to the
+ program at the time programBinary() is called.
+
+ \sa setProgramBinary(), programBinaryFormats()
+*/
+QByteArray QGLShaderProgram::programBinary(int *format) const
+{
+#if defined(QT_OPENGL_ES_2)
+ if (!isLinked())
+ return QByteArray();
+
+ // Get the length of the binary data, bailing out if there is none.
+ GLint length = 0;
+ glGetProgramiv(d->program, GL_PROGRAM_BINARY_LENGTH_OES, &length);
+ if (length <= 0)
+ return QByteArray();
+
+ // Retrieve the binary data.
+ QByteArray binary(length, 0);
+ GLenum binaryFormat;
+ glGetProgramBinaryOES(d->program, length, 0, &binaryFormat, binary.data());
+ if (format)
+ *format = (int)binaryFormat;
+ return binary;
+#else
+ Q_UNUSED(format);
+ return QByteArray();
+#endif
+}
+
+/*!
+ Sets the \a binary for this shader program according to \a format.
+ Returns true if the binary was set, or false if the binary format
+ is not supported or this system does not support program binaries.
+ The program will be linked if the load succeeds.
+
+ \sa programBinary(), programBinaryFormats(), isLinked()
+*/
+bool QGLShaderProgram::setProgramBinary(int format, const QByteArray& binary)
+{
+#if defined(QT_OPENGL_ES_2)
+ // Load the binary and check that it was linked correctly.
+ glProgramBinaryOES(d->program, (GLenum)format,
+ binary.constData(), binary.size());
+ GLint value = 0;
+ glGetProgramiv(d->program, GL_LINK_STATUS, &value);
+ d->linked = (value != 0);
+ value = 0;
+ glGetProgramiv(d->program, GL_INFO_LOG_LENGTH, &value);
+ d->log = QString();
+ if (value > 1) {
+ char *logbuf = new char [value];
+ GLint len;
+ glGetProgramInfoLog(d->program, value, &len, logbuf);
+ d->log = QString::fromLatin1(logbuf);
+ qWarning() << "QGLShaderProgram::setProgramBinary:" << d->log;
+ delete [] logbuf;
+ }
+ return d->linked;
+#else
+ Q_UNUSED(format);
+ Q_UNUSED(binary);
+ return false;
+#endif
+}
+
+/*!
+ Returns the list of program binary formats that are accepted by
+ this system for use with setProgramBinary().
+
+ \sa programBinary(), setProgramBinary()
+*/
+QList<int> QGLShaderProgram::programBinaryFormats()
+{
+#if defined(QT_OPENGL_ES_2)
+ GLint count = 0;
+ glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &count);
+ if (count <= 0)
+ return QList<int>();
+ QVector<int> list;
+ list.resize(count);
+ glGetIntegerv(GL_PROGRAM_BINARY_FORMATS_OES, list.data());
+ return list.toList();
+#else
+ return QList<int>();
+#endif
+}
+
+/*!
+ Links together the shaders that were added to this program with
+ addShader(). Returns true if the link was successful or
+ false otherwise. If the link failed, the error messages can
+ be retrieved with log().
+
+ Subclasses can override this function to initialize attributes
+ and uniform variables for use in specific shader programs.
+
+ If the shader program was already linked, calling this
+ function again will force it to be re-linked.
+
+ \sa addShader(), log()
+*/
+bool QGLShaderProgram::link()
+{
+ if (!d->program)
+ return false;
+ if (d->hasPartialShaders) {
+ // Compile the partial vertex and fragment shaders.
+ QByteArray vertexSource;
+ QByteArray fragmentSource;
+ foreach (QGLShader *shader, d->shaders) {
+ if (shader->shaderType() == QGLShader::PartialVertexShader)
+ vertexSource += shader->sourceCode();
+ else if (shader->shaderType() == QGLShader::PartialFragmentShader)
+ fragmentSource += shader->sourceCode();
+ }
+ if (vertexSource.isEmpty()) {
+ if (d->vertexShader) {
+ glDetachShader(d->program, d->vertexShader->d->shader);
+ delete d->vertexShader;
+ d->vertexShader = 0;
+ }
+ } else {
+ if (!d->vertexShader) {
+ d->vertexShader =
+ new QGLShader(QGLShader::VertexShader, this);
+ }
+ if (!d->vertexShader->setSourceCode(vertexSource)) {
+ d->log = d->vertexShader->log();
+ return false;
+ }
+ glAttachShader(d->program, d->vertexShader->d->shader);
+ }
+ if (fragmentSource.isEmpty()) {
+ if (d->fragmentShader) {
+ glDetachShader(d->program, d->fragmentShader->d->shader);
+ delete d->fragmentShader;
+ d->fragmentShader = 0;
+ }
+ } else {
+ if (!d->fragmentShader) {
+ d->fragmentShader =
+ new QGLShader(QGLShader::FragmentShader, this);
+ }
+ if (!d->fragmentShader->setSourceCode(fragmentSource)) {
+ d->log = d->fragmentShader->log();
+ return false;
+ }
+ glAttachShader(d->program, d->fragmentShader->d->shader);
+ }
+ }
+ glLinkProgram(d->program);
+ GLint value = 0;
+ glGetProgramiv(d->program, GL_LINK_STATUS, &value);
+ d->linked = (value != 0);
+ value = 0;
+ glGetProgramiv(d->program, GL_INFO_LOG_LENGTH, &value);
+ d->log = QString();
+ if (value > 1) {
+ char *logbuf = new char [value];
+ GLint len;
+ glGetProgramInfoLog(d->program, value, &len, logbuf);
+ d->log = QString::fromLatin1(logbuf);
+ qWarning() << "QGLShaderProgram::link:" << d->log;
+ delete [] logbuf;
+ }
+ return d->linked;
+}
+
+/*!
+ Returns true if this shader program has been linked; false otherwise.
+
+ \sa link()
+*/
+bool QGLShaderProgram::isLinked() const
+{
+ return d->linked;
+}
+
+/*!
+ Returns the errors and warnings that occurred during the last link()
+ or addShader() with explicitly specified source code.
+
+ \sa link()
+*/
+QString QGLShaderProgram::log() const
+{
+ return d->log;
+}
+
+/*!
+ Enable use of this shader program in the currently active QGLContext.
+ Returns true if the program was successfully enabled; false
+ otherwise. If the shader program has not yet been linked,
+ or it needs to be re-linked, this function will call link().
+
+ \sa link(), disable()
+*/
+bool QGLShaderProgram::enable()
+{
+ if (!d->program)
+ return false;
+ if (!d->linked && !link())
+ return false;
+ glUseProgram(d->program);
+ return true;
+}
+
+#undef ctx
+#define ctx QGLContext::currentContext()
+
+/*!
+ Disables the active shader program in the current QGLContext.
+ This is equivalent to calling \c{glUseProgram(0)}.
+
+ \sa enable()
+*/
+void QGLShaderProgram::disable()
+{
+#if defined(QT_OPENGL_ES_2)
+ glUseProgram(0);
+#else
+ if (glUseProgram)
+ glUseProgram(0);
+#endif
+}
+
+#undef ctx
+#define ctx d->context
+
+/*!
+ Returns the OpenGL identifier associated with this shader program.
+
+ \sa QGLShader::shaderId()
+*/
+GLuint QGLShaderProgram::programId() const
+{
+ return d->program;
+}
+
+/*!
+ Binds the attribute \a name to the specified \a location. This
+ function can be called before or after the program has been linked.
+ Any attributes that have not been explicitly bound when the program
+ is linked will be assigned locations automatically.
+
+ \sa attributeLocation()
+*/
+void QGLShaderProgram::bindAttributeLocation(const char *name, int location)
+{
+ glBindAttribLocation(d->program, location, name);
+}
+
+/*!
+ \overload
+
+ Binds the attribute \a name to the specified \a location. This
+ function can be called before or after the program has been linked.
+ Any attributes that have not been explicitly bound when the program
+ is linked will be assigned locations automatically.
+
+ \sa attributeLocation()
+*/
+void QGLShaderProgram::bindAttributeLocation(const QByteArray& name, int location)
+{
+ glBindAttribLocation(d->program, location, name.constData());
+}
+
+/*!
+ \overload
+
+ Binds the attribute \a name to the specified \a location. This
+ function can be called before or after the program has been linked.
+ Any attributes that have not been explicitly bound when the program
+ is linked will be assigned locations automatically.
+
+ \sa attributeLocation()
+*/
+void QGLShaderProgram::bindAttributeLocation(const QString& name, int location)
+{
+ glBindAttribLocation(d->program, location, name.toLatin1().constData());
+}
+
+/*!
+ Returns the location of the attribute \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ attribute for this shader program.
+
+ \sa uniformLocation(), bindAttributeLocation()
+*/
+int QGLShaderProgram::attributeLocation(const char *name) const
+{
+ if (d->linked) {
+ return glGetAttribLocation(d->program, name);
+ } else {
+ qWarning() << "QGLShaderProgram::attributeLocation(" << name
+ << "): shader program is not linked";
+ return -1;
+ }
+}
+
+/*!
+ \overload
+
+ Returns the location of the attribute \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ attribute for this shader program.
+
+ \sa uniformLocation(), bindAttributeLocation()
+*/
+int QGLShaderProgram::attributeLocation(const QByteArray& name) const
+{
+ return attributeLocation(name.constData());
+}
+
+/*!
+ \overload
+
+ Returns the location of the attribute \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ attribute for this shader program.
+
+ \sa uniformLocation(), bindAttributeLocation()
+*/
+int QGLShaderProgram::attributeLocation(const QString& name) const
+{
+ return attributeLocation(name.toLatin1().constData());
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, GLfloat value)
+{
+ if (location != -1)
+ glVertexAttrib1fv(location, &value);
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, GLfloat value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, GLfloat x, GLfloat y)
+{
+ if (location != -1) {
+ GLfloat values[2] = {x, y};
+ glVertexAttrib2fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, GLfloat x, GLfloat y)
+{
+ setAttributeValue(attributeLocation(name), x, y);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (int location, GLfloat x, GLfloat y, GLfloat z)
+{
+ if (location != -1) {
+ GLfloat values[3] = {x, y, z};
+ glVertexAttrib3fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z)
+{
+ setAttributeValue(attributeLocation(name), x, y, z);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ if (location != -1) {
+ GLfloat values[4] = {x, y, z, w};
+ glVertexAttrib4fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ setAttributeValue(attributeLocation(name), x, y, z, w);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QVector2D& value)
+{
+ if (location != -1)
+ glVertexAttrib2fv(location, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QVector2D& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QVector3D& value)
+{
+ if (location != -1)
+ glVertexAttrib3fv(location, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QVector3D& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QVector4D& value)
+{
+ if (location != -1)
+ glVertexAttrib4fv(location, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QVector4D& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QColor& value)
+{
+ if (location != -1) {
+ GLfloat values[4] = {value.redF(), value.greenF(), value.blueF(), value.alphaF()};
+ glVertexAttrib4fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QColor& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to the
+ contents of \a values, which contains \a columns elements, each
+ consisting of \a rows elements. The \a rows value should be
+ 1, 2, 3, or 4. This function is typically used to set matrix
+ values and column vectors.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (int location, const GLfloat *values, int columns, int rows)
+{
+ if (rows < 1 || rows > 4) {
+ qWarning() << "QGLShaderProgram::setAttributeValue: rows" << rows << "not supported";
+ return;
+ }
+ if (location != -1) {
+ while (columns-- > 0) {
+ if (rows == 1)
+ glVertexAttrib1fv(location, values);
+ else if (rows == 2)
+ glVertexAttrib2fv(location, values);
+ else if (rows == 3)
+ glVertexAttrib3fv(location, values);
+ else
+ glVertexAttrib4fv(location, values);
+ values += rows;
+ ++location;
+ }
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to the
+ contents of \a values, which contains \a columns elements, each
+ consisting of \a rows elements. The \a rows value should be
+ 1, 2, 3, or 4. This function is typically used to set matrix
+ values and column vectors.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (const char *name, const GLfloat *values, int columns, int rows)
+{
+ setAttributeValue(attributeLocation(name), values, columns, rows);
+}
+
+/*!
+ Sets an array of vertex \a values on the attribute at \a location
+ in this shader program. The \a size indicates the number of
+ components per vertex (1, 2, 3, or 4), and the \a stride indicates
+ the number of bytes between vertices. A default \a stride value
+ of zero indicates that the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const GLfloat *values, int size, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, size, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ Sets an array of 2D vertex \a values on the attribute at \a location
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const QVector2D *values, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ Sets an array of 3D vertex \a values on the attribute at \a location
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const QVector3D *values, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ Sets an array of 4D vertex \a values on the attribute at \a location
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const QVector4D *values, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ \overload
+
+ Sets an array of vertex \a values on the attribute called \a name
+ in this shader program. The \a size indicates the number of
+ components per vertex (1, 2, 3, or 4), and the \a stride indicates
+ the number of bytes between vertices. A default \a stride value
+ of zero indicates that the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const GLfloat *values, int size, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, size, stride);
+}
+
+/*!
+ \overload
+
+ Sets an array of 2D vertex \a values on the attribute called \a name
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const QVector2D *values, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, stride);
+}
+
+/*!
+ \overload
+
+ Sets an array of 3D vertex \a values on the attribute called \a name
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const QVector3D *values, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, stride);
+}
+
+/*!
+ \overload
+
+ Sets an array of 4D vertex \a values on the attribute called \a name
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const QVector4D *values, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, stride);
+}
+
+/*!
+ Disables the vertex array at \a location in this shader program
+ that was enabled by a previous call to setAttributeArray().
+
+ \sa setAttributeArray(), setAttributeValue(), setUniformValue()
+*/
+void QGLShaderProgram::disableAttributeArray(int location)
+{
+ if (location != -1)
+ glDisableVertexAttribArray(location);
+}
+
+/*!
+ \overload
+
+ Disables the vertex array called \a name in this shader program
+ that was enabled by a previous call to setAttributeArray().
+
+ \sa setAttributeArray(), setAttributeValue(), setUniformValue()
+*/
+void QGLShaderProgram::disableAttributeArray(const char *name)
+{
+ disableAttributeArray(attributeLocation(name));
+}
+
+/*!
+ Returns the location of the uniform variable \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ uniform variable for this shader program.
+
+ \sa attributeLocation()
+*/
+int QGLShaderProgram::uniformLocation(const char *name) const
+{
+ if (d->linked) {
+ return glGetUniformLocation(d->program, name);
+ } else {
+ qWarning() << "QGLShaderProgram::uniformLocation(" << name
+ << "): shader program is not linked";
+ return -1;
+ }
+}
+
+/*!
+ \overload
+
+ Returns the location of the uniform variable \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ uniform variable for this shader program.
+
+ \sa attributeLocation()
+*/
+int QGLShaderProgram::uniformLocation(const QByteArray& name) const
+{
+ return uniformLocation(name.constData());
+}
+
+/*!
+ \overload
+
+ Returns the location of the uniform variable \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ uniform variable for this shader program.
+
+ \sa attributeLocation()
+*/
+int QGLShaderProgram::uniformLocation(const QString& name) const
+{
+ return uniformLocation(name.toLatin1().constData());
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLfloat value)
+{
+ if (location != -1)
+ glUniform1fv(location, 1, &value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLfloat value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLint value)
+{
+ if (location != -1)
+ glUniform1i(location, value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLint value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+ This function should be used when setting sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLuint value)
+{
+ if (location != -1)
+ glUniform1i(location, value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value. This function should be used when setting sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLuint value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLfloat x, GLfloat y)
+{
+ if (location != -1) {
+ GLfloat values[2] = {x, y};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLfloat x, GLfloat y)
+{
+ setUniformValue(uniformLocation(name), x, y);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (int location, GLfloat x, GLfloat y, GLfloat z)
+{
+ if (location != -1) {
+ GLfloat values[3] = {x, y, z};
+ glUniform3fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z)
+{
+ setUniformValue(uniformLocation(name), x, y, z);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ if (location != -1) {
+ GLfloat values[4] = {x, y, z, w};
+ glUniform4fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ setUniformValue(uniformLocation(name), x, y, z, w);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QVector2D& value)
+{
+ if (location != -1)
+ glUniform2fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QVector2D& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QVector3D& value)
+{
+ if (location != -1)
+ glUniform3fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QVector3D& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QVector4D& value)
+{
+ if (location != -1)
+ glUniform4fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QVector4D& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the red, green, blue, and alpha components of \a color.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QColor& color)
+{
+ if (location != -1) {
+ GLfloat values[4] = {color.redF(), color.greenF(), color.blueF(), color.alphaF()};
+ glUniform4fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the red, green, blue, and alpha components of \a color.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QColor& color)
+{
+ setUniformValue(uniformLocation(name), color);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the x and y coordinates of \a point.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QPoint& point)
+{
+ if (location != -1) {
+ GLfloat values[4] = {point.x(), point.y()};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable associated with \a name in the current
+ context to the x and y coordinates of \a point.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QPoint& point)
+{
+ setUniformValue(uniformLocation(name), point);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the x and y coordinates of \a point.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QPointF& point)
+{
+ if (location != -1) {
+ GLfloat values[4] = {point.x(), point.y()};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable associated with \a name in the current
+ context to the x and y coordinates of \a point.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QPointF& point)
+{
+ setUniformValue(uniformLocation(name), point);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the width and height of the given \a size.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QSize& size)
+{
+ if (location != -1) {
+ GLfloat values[4] = {size.width(), size.width()};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable associated with \a name in the current
+ context to the width and height of the given \a size.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QSize& size)
+{
+ setUniformValue(uniformLocation(name), size);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the width and height of the given \a size.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QSizeF& size)
+{
+ if (location != -1) {
+ GLfloat values[4] = {size.width(), size.height()};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable associated with \a name in the current
+ context to the width and height of the given \a size.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QSizeF& size)
+{
+ setUniformValue(uniformLocation(name), size);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix2x2& value)
+{
+ if (location != -1)
+ glUniformMatrix2fv(location, 1, GL_FALSE, value.data());
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x2& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix2x3& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix2x3fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix2x3fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform3fv(location, 2, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform3fv(location, 2, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x3& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix2x4& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix2x4fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix2x4fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform4fv(location, 2, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform4fv(location, 2, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 3x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix3x2& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix3x2fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix3x2fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform2fv(location, 3, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform2fv(location, 3, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x2& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 3x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix3x3& value)
+{
+ if (location != -1)
+ glUniformMatrix3fv(location, 1, GL_FALSE, value.data());
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x3& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 3x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix3x4& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix3x4fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix3x4fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform4fv(location, 3, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform4fv(location, 3, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 4x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix4x2& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix4x2fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix4x2fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform2fv(location, 4, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform2fv(location, 4, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x2& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 4x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix4x3& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix4x3fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix4x3fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform3fv(location, 4, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform3fv(location, 4, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x3& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 4x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix4x4& value)
+{
+ if (location != -1)
+ glUniformMatrix4fv(location, 1, GL_FALSE, value.data());
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable at \a location in the current context
+ to a 4x4 matrix \a value. The matrix elements must be specified
+ in column-major order.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const GLfloat value[4][4])
+{
+ if (location != -1)
+ glUniformMatrix4fv(location, 1, GL_FALSE, value[0]);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x4 matrix \a value. The matrix elements must be specified
+ in column-major order.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[4][4])
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to a
+ 3x3 transformation matrix \a value that is specified as a QTransform value.
+
+ To set a QTransform value as a 4x4 matrix in a shader, use
+ \c{setUniformValue(location, QMatrix4x4(value))}.
+*/
+void QGLShaderProgram::setUniformValue(int location, const QTransform& value)
+{
+ if (location != -1) {
+ GLfloat mat[3][3] = {
+ {value.m11(), value.m12(), value.m13()},
+ {value.m21(), value.m22(), value.m23()},
+ {value.m31(), value.m32(), value.m33()}
+ };
+ glUniformMatrix3fv(location, 1, GL_FALSE, mat[0]);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to a
+ 3x3 transformation matrix \a value that is specified as a QTransform value.
+
+ To set a QTransform value as a 4x4 matrix in a shader, use
+ \c{setUniformValue(name, QMatrix4x4(value))}.
+*/
+void QGLShaderProgram::setUniformValue
+ (const char *name, const QTransform& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const GLint *values, int count)
+{
+ if (location != -1)
+ glUniform1iv(location, count, values);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray
+ (const char *name, const GLint *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count elements of \a values. This overload
+ should be used when setting an array of sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const GLuint *values, int count)
+{
+ if (location != -1)
+ glUniform1iv(location, count, reinterpret_cast<const GLint *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count elements of \a values. This overload
+ should be used when setting an array of sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray
+ (const char *name, const GLuint *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count elements of \a values. Each element
+ has \a size components. The \a size must be 1, 2, 3, or 4.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const GLfloat *values, int count, int size)
+{
+ if (location != -1) {
+ if (size == 1)
+ glUniform1fv(location, count, values);
+ else if (size == 2)
+ glUniform2fv(location, count, values);
+ else if (size == 3)
+ glUniform3fv(location, count, values);
+ else if (size == 4)
+ glUniform4fv(location, count, values);
+ else
+ qWarning() << "QGLShaderProgram::setUniformValue: size" << size << "not supported";
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count elements of \a values. Each element
+ has \a size components. The \a size must be 1, 2, 3, or 4.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray
+ (const char *name, const GLfloat *values, int count, int size)
+{
+ setUniformValueArray(uniformLocation(name), values, count, size);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QVector2D *values, int count)
+{
+ if (location != -1)
+ glUniform2fv(location, count, reinterpret_cast<const GLfloat *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QVector2D *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QVector3D *values, int count)
+{
+ if (location != -1)
+ glUniform3fv(location, count, reinterpret_cast<const GLfloat *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QVector3D *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QVector4D *values, int count)
+{
+ if (location != -1)
+ glUniform4fv(location, count, reinterpret_cast<const GLfloat *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QVector4D *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+// We may have to repack matrix arrays if the matrix types
+// contain additional flag bits. Especially QMatrix4x4.
+#define setUniformMatrixArray(func,location,values,count,type,cols,rows) \
+ if (location == -1 || count <= 0) \
+ return; \
+ if (count == 1 || sizeof(type) == cols * rows * sizeof(GLfloat)) { \
+ func(location, count, GL_FALSE, values->constData()); \
+ } else { \
+ QVarLengthArray<GLfloat> temp(cols * rows * count); \
+ for (int index = 0; index < count; ++index) { \
+ qMemCopy(temp.data() + cols * rows * index, \
+ values[index].constData(), cols * rows * sizeof(GLfloat)); \
+ } \
+ func(location, count, GL_FALSE, temp.constData()); \
+ }
+#if !defined(QT_OPENGL_ES_2)
+#define setUniformGenericMatrixArray(func,colfunc,location,values,count,type,cols,rows) \
+ if (location == -1 || count <= 0) \
+ return; \
+ if (count == 1 || sizeof(type) == cols * rows * sizeof(GLfloat)) { \
+ if (func) \
+ func(location, count, GL_FALSE, values->constData()); \
+ else \
+ colfunc(location, cols * count, values->constData()); \
+ } else { \
+ QVarLengthArray<GLfloat> temp(cols * rows * count); \
+ for (int index = 0; index < count; ++index) { \
+ qMemCopy(temp.data() + cols * rows * index, \
+ values[index].constData(), cols * rows * sizeof(GLfloat)); \
+ } \
+ if (func) \
+ func(location, count, GL_FALSE, temp.constData()); \
+ else \
+ colfunc(location, count * cols, temp.constData()); \
+ }
+#else
+#define setUniformGenericMatrixArray(func,colfunc,location,values,count,type,cols,rows) \
+ if (location == -1 || count <= 0) \
+ return; \
+ if (count == 1 || sizeof(type) == cols * rows * sizeof(GLfloat)) { \
+ colfunc(location, cols * count, values->constData()); \
+ } else { \
+ QVarLengthArray<GLfloat> temp(cols * rows * count); \
+ for (int index = 0; index < count; ++index) { \
+ qMemCopy(temp.data() + cols * rows * index, \
+ values[index].constData(), cols * rows * sizeof(GLfloat)); \
+ } \
+ colfunc(location, count * cols, temp.constData()); \
+ }
+#endif
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x2 *values, int count)
+{
+ setUniformMatrixArray
+ (glUniformMatrix2fv, location, values, count, QMatrix2x2, 2, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x2 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x3 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix2x3fv, glUniform3fv, location, values, count,
+ QMatrix2x3, 2, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x3 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x4 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix2x4fv, glUniform4fv, location, values, count,
+ QMatrix2x4, 2, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x4 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x2 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix3x2fv, glUniform2fv, location, values, count,
+ QMatrix3x2, 3, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x2 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x3 *values, int count)
+{
+ setUniformMatrixArray
+ (glUniformMatrix3fv, location, values, count, QMatrix3x3, 3, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x3 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x4 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix3x4fv, glUniform4fv, location, values, count,
+ QMatrix3x4, 3, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x4 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x2 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix4x2fv, glUniform2fv, location, values, count,
+ QMatrix4x2, 4, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x2 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x3 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix4x3fv, glUniform3fv, location, values, count,
+ QMatrix4x3, 4, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x3 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x4 *values, int count)
+{
+ setUniformMatrixArray
+ (glUniformMatrix4fv, location, values, count, QMatrix4x4, 4, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Returns true if shader programs written in the OpenGL Shading
+ Language (GLSL) are supported on this system; false otherwise.
+
+ The \a context is used to resolve the GLSL extensions.
+ If \a context is null, then QGLContext::currentContext() is used.
+*/
+bool QGLShaderProgram::hasShaderPrograms(const QGLContext *context)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!context)
+ context = QGLContext::currentContext();
+ if (!context)
+ return false;
+ return qt_resolve_glsl_extensions(const_cast<QGLContext *>(context));
+#else
+ Q_UNUSED(context);
+ return true;
+#endif
+}
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
new file mode 100644
index 0000000..b69d28e
--- /dev/null
+++ b/src/opengl/qglshaderprogram.h
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGLSHADERPROGRAM_H
+#define QGLSHADERPROGRAM_H
+
+#include <QtOpenGL/qgl.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include <QtGui/qmatrix4x4.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(OpenGL)
+
+#if !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+
+class QGLShaderProgram;
+class QGLShaderPrivate;
+
+class Q_OPENGL_EXPORT QGLShader : public QObject
+{
+ Q_OBJECT
+public:
+ enum ShaderType
+ {
+ VertexShader,
+ FragmentShader,
+ PartialVertexShader,
+ PartialFragmentShader
+ };
+
+ explicit QGLShader(QGLShader::ShaderType type, QObject *parent = 0);
+ explicit QGLShader(const QString& fileName, QObject *parent = 0);
+ QGLShader(const QString& fileName, QGLShader::ShaderType type, QObject *parent = 0);
+ QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent = 0);
+ QGLShader(const QString& fileName, const QGLContext *context, QObject *parent = 0);
+ QGLShader(const QString& fileName, QGLShader::ShaderType type, const QGLContext *context, QObject *parent = 0);
+ virtual ~QGLShader();
+
+ bool isValid() const;
+
+ QGLShader::ShaderType shaderType() const;
+
+ bool setSourceCode(const char *source);
+ bool setSourceCode(const QByteArray& source);
+ bool setSourceCode(const QString& source);
+ bool setSourceCodeFile(const QString& fileName);
+
+ bool setBinaryCode(GLenum format, const void *binary, int length);
+ bool setBinaryCode(QGLShader& otherShader, GLenum format, const void *binary, int length);
+
+ static QList<GLenum> shaderBinaryFormats();
+
+ QByteArray sourceCode() const;
+
+ bool isCompiled() const;
+ QString log() const;
+
+ GLuint shaderId() const;
+
+private:
+ QGLShaderPrivate *d;
+
+ friend class QGLShaderProgram;
+
+ Q_DISABLE_COPY(QGLShader);
+};
+
+class QGLShaderProgramPrivate;
+
+class Q_OPENGL_EXPORT QGLShaderProgram : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QGLShaderProgram(QObject *parent = 0);
+ explicit QGLShaderProgram(const QGLContext *context, QObject *parent = 0);
+ virtual ~QGLShaderProgram();
+
+ bool isValid() const;
+
+ bool addShader(QGLShader *shader);
+ void removeShader(QGLShader *shader);
+ QList<QGLShader *> shaders() const;
+
+ bool addShader(QGLShader::ShaderType type, const char *source);
+ bool addShader(QGLShader::ShaderType type, const QByteArray& source);
+ bool addShader(QGLShader::ShaderType type, const QString& source);
+
+ void removeAllShaders();
+
+ QByteArray programBinary(int *format) const;
+ bool setProgramBinary(int format, const QByteArray& binary);
+ static QList<int> programBinaryFormats();
+
+ virtual bool link();
+ bool isLinked() const;
+ QString log() const;
+
+ bool enable();
+ static void disable();
+
+ GLuint programId() const;
+
+ void bindAttributeLocation(const char *name, int location);
+ void bindAttributeLocation(const QByteArray& name, int location);
+ void bindAttributeLocation(const QString& name, int location);
+
+ int attributeLocation(const char *name) const;
+ int attributeLocation(const QByteArray& name) const;
+ int attributeLocation(const QString& name) const;
+
+ void setAttributeValue(int location, GLfloat value);
+ void setAttributeValue(int location, GLfloat x, GLfloat y);
+ void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z);
+ void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setAttributeValue(int location, const QVector2D& value);
+ void setAttributeValue(int location, const QVector3D& value);
+ void setAttributeValue(int location, const QVector4D& value);
+ void setAttributeValue(int location, const QColor& value);
+ void setAttributeValue(int location, const GLfloat *values, int columns, int rows);
+
+ void setAttributeValue(const char *name, GLfloat value);
+ void setAttributeValue(const char *name, GLfloat x, GLfloat y);
+ void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z);
+ void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setAttributeValue(const char *name, const QVector2D& value);
+ void setAttributeValue(const char *name, const QVector3D& value);
+ void setAttributeValue(const char *name, const QVector4D& value);
+ void setAttributeValue(const char *name, const QColor& value);
+ void setAttributeValue(const char *name, const GLfloat *values, int columns, int rows);
+
+ void setAttributeArray
+ (int location, const GLfloat *values, int size, int stride = 0);
+ void setAttributeArray
+ (int location, const QVector2D *values, int stride = 0);
+ void setAttributeArray
+ (int location, const QVector3D *values, int stride = 0);
+ void setAttributeArray
+ (int location, const QVector4D *values, int stride = 0);
+ void setAttributeArray
+ (const char *name, const GLfloat *values, int size, int stride = 0);
+ void setAttributeArray
+ (const char *name, const QVector2D *values, int stride = 0);
+ void setAttributeArray
+ (const char *name, const QVector3D *values, int stride = 0);
+ void setAttributeArray
+ (const char *name, const QVector4D *values, int stride = 0);
+ void disableAttributeArray(int location);
+ void disableAttributeArray(const char *name);
+
+ int uniformLocation(const char *name) const;
+ int uniformLocation(const QByteArray& name) const;
+ int uniformLocation(const QString& name) const;
+
+ void setUniformValue(int location, GLfloat value);
+ void setUniformValue(int location, GLint value);
+ void setUniformValue(int location, GLuint value);
+ void setUniformValue(int location, GLfloat x, GLfloat y);
+ void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z);
+ void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setUniformValue(int location, const QVector2D& value);
+ void setUniformValue(int location, const QVector3D& value);
+ void setUniformValue(int location, const QVector4D& value);
+ void setUniformValue(int location, const QColor& color);
+ void setUniformValue(int location, const QPoint& point);
+ void setUniformValue(int location, const QPointF& point);
+ void setUniformValue(int location, const QSize& size);
+ void setUniformValue(int location, const QSizeF& size);
+ void setUniformValue(int location, const QMatrix2x2& value);
+ void setUniformValue(int location, const QMatrix2x3& value);
+ void setUniformValue(int location, const QMatrix2x4& value);
+ void setUniformValue(int location, const QMatrix3x2& value);
+ void setUniformValue(int location, const QMatrix3x3& value);
+ void setUniformValue(int location, const QMatrix3x4& value);
+ void setUniformValue(int location, const QMatrix4x2& value);
+ void setUniformValue(int location, const QMatrix4x3& value);
+ void setUniformValue(int location, const QMatrix4x4& value);
+ void setUniformValue(int location, const GLfloat value[4][4]);
+ void setUniformValue(int location, const QTransform& value);
+
+ void setUniformValue(const char *name, GLfloat value);
+ void setUniformValue(const char *name, GLint value);
+ void setUniformValue(const char *name, GLuint value);
+ void setUniformValue(const char *name, GLfloat x, GLfloat y);
+ void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z);
+ void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setUniformValue(const char *name, const QVector2D& value);
+ void setUniformValue(const char *name, const QVector3D& value);
+ void setUniformValue(const char *name, const QVector4D& value);
+ void setUniformValue(const char *name, const QColor& color);
+ void setUniformValue(const char *name, const QPoint& point);
+ void setUniformValue(const char *name, const QPointF& point);
+ void setUniformValue(const char *name, const QSize& size);
+ void setUniformValue(const char *name, const QSizeF& size);
+ void setUniformValue(const char *name, const QMatrix2x2& value);
+ void setUniformValue(const char *name, const QMatrix2x3& value);
+ void setUniformValue(const char *name, const QMatrix2x4& value);
+ void setUniformValue(const char *name, const QMatrix3x2& value);
+ void setUniformValue(const char *name, const QMatrix3x3& value);
+ void setUniformValue(const char *name, const QMatrix3x4& value);
+ void setUniformValue(const char *name, const QMatrix4x2& value);
+ void setUniformValue(const char *name, const QMatrix4x3& value);
+ void setUniformValue(const char *name, const QMatrix4x4& value);
+ void setUniformValue(const char *name, const GLfloat value[4][4]);
+ void setUniformValue(const char *name, const QTransform& value);
+
+ void setUniformValueArray(int location, const GLfloat *values, int count, int size);
+ void setUniformValueArray(int location, const GLint *values, int count);
+ void setUniformValueArray(int location, const GLuint *values, int count);
+ void setUniformValueArray(int location, const QVector2D *values, int count);
+ void setUniformValueArray(int location, const QVector3D *values, int count);
+ void setUniformValueArray(int location, const QVector4D *values, int count);
+ void setUniformValueArray(int location, const QMatrix2x2 *values, int count);
+ void setUniformValueArray(int location, const QMatrix2x3 *values, int count);
+ void setUniformValueArray(int location, const QMatrix2x4 *values, int count);
+ void setUniformValueArray(int location, const QMatrix3x2 *values, int count);
+ void setUniformValueArray(int location, const QMatrix3x3 *values, int count);
+ void setUniformValueArray(int location, const QMatrix3x4 *values, int count);
+ void setUniformValueArray(int location, const QMatrix4x2 *values, int count);
+ void setUniformValueArray(int location, const QMatrix4x3 *values, int count);
+ void setUniformValueArray(int location, const QMatrix4x4 *values, int count);
+
+ void setUniformValueArray(const char *name, const GLfloat *values, int count, int size);
+ void setUniformValueArray(const char *name, const GLint *values, int count);
+ void setUniformValueArray(const char *name, const GLuint *values, int count);
+ void setUniformValueArray(const char *name, const QVector2D *values, int count);
+ void setUniformValueArray(const char *name, const QVector3D *values, int count);
+ void setUniformValueArray(const char *name, const QVector4D *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix2x2 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix2x3 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix2x4 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix3x2 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix3x3 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix3x4 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix4x2 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix4x3 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix4x4 *values, int count);
+
+ static bool hasShaderPrograms(const QGLContext *context = 0);
+
+private:
+ QGLShaderProgramPrivate *d;
+
+ Q_DISABLE_COPY(QGLShaderProgram);
+
+ bool init();
+};
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/script/qscriptengine_p.cpp b/src/script/qscriptengine_p.cpp
index a2e58de..84a420d 100644
--- a/src/script/qscriptengine_p.cpp
+++ b/src/script/qscriptengine_p.cpp
@@ -1662,6 +1662,11 @@ bool QScriptEnginePrivate::convert(const QScriptValueImpl &value,
return false;
}
+QScriptEngine::DemarshalFunction QScriptEnginePrivate::demarshalFunction(int type) const
+{
+ return m_customTypes.value(type).demarshal;
+}
+
QScriptValuePrivate *QScriptEnginePrivate::registerValue(const QScriptValueImpl &value)
{
if (value.isString()) {
diff --git a/src/script/qscriptenginefwd_p.h b/src/script/qscriptenginefwd_p.h
index 2ea66c5..855317c 100644
--- a/src/script/qscriptenginefwd_p.h
+++ b/src/script/qscriptenginefwd_p.h
@@ -350,6 +350,7 @@ public:
QScriptValueImpl create(int type, const void *ptr);
static bool convert(const QScriptValueImpl &value, int type, void *ptr,
QScriptEnginePrivate *eng);
+ QScriptEngine::DemarshalFunction demarshalFunction(int type) const;
QScriptValueImpl arrayFromStringList(const QStringList &lst);
static QStringList stringListFromArray(const QScriptValueImpl &arr);
diff --git a/src/script/qscriptextqobject.cpp b/src/script/qscriptextqobject.cpp
index d18c3da..802653a 100644
--- a/src/script/qscriptextqobject.cpp
+++ b/src/script/qscriptextqobject.cpp
@@ -425,7 +425,7 @@ static void callQtMethod(QScriptContextPrivate *context, QMetaMethod::MethodType
matchDistance += 10;
}
}
- } else if (actual.isNumber()) {
+ } else if (actual.isNumber() || actual.isString()) {
// see if it's an enum value
QMetaEnum m;
if (argType.isMetaEnum()) {
@@ -436,11 +436,21 @@ static void callQtMethod(QScriptContextPrivate *context, QMetaMethod::MethodType
m = meta->enumerator(mi);
}
if (m.isValid()) {
- int ival = actual.toInt32();
- if (m.valueToKey(ival) != 0) {
- qVariantSetValue(v, ival);
- converted = true;
- matchDistance += 10;
+ if (actual.isNumber()) {
+ int ival = actual.toInt32();
+ if (m.valueToKey(ival) != 0) {
+ qVariantSetValue(v, ival);
+ converted = true;
+ matchDistance += 10;
+ }
+ } else {
+ QString sval = actual.toString();
+ int ival = m.keyToValue(sval.toLatin1());
+ if (ival != -1) {
+ qVariantSetValue(v, ival);
+ converted = true;
+ matchDistance += 10;
+ }
}
}
}
@@ -726,7 +736,7 @@ static void callQtMethod(QScriptContextPrivate *context, QMetaMethod::MethodType
meta->static_metacall(QMetaObject::CreateInstance, chosenIndex, params);
} else {
Q_ASSERT(thisQObject != 0);
- thisQObject->qt_metacall(QMetaObject::InvokeMetaMethod, chosenIndex, params);
+ QMetaObject::metacall(thisQObject, QMetaObject::InvokeMetaMethod, chosenIndex, params);
}
if (scriptable)
@@ -1809,7 +1819,16 @@ void QScript::QtPropertyFunction::execute(QScriptContextPrivate *context)
}
} else {
// set
- QVariant v = variantFromValue(eng_p, prop.userType(), context->argument(0));
+ QScriptValueImpl arg = context->argument(0);
+ QVariant v;
+ if (prop.isEnumType() && arg.isString()
+ && !eng_p->demarshalFunction(prop.userType())) {
+ // give QMetaProperty::write() a chance to convert from
+ // string to enum value
+ v = arg.toString();
+ } else {
+ v = variantFromValue(eng_p, prop.userType(), arg);
+ }
QScriptable *scriptable = scriptableFromQObject(qobject);
QScriptEngine *oldEngine = 0;
diff --git a/src/src.pro b/src/src.pro
index f40c6ad..e35c3f5 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -27,6 +27,7 @@ contains(QT_CONFIG, webkit) {
SRC_SUBDIRS += src_webkit
}
contains(QT_CONFIG, scripttools): SRC_SUBDIRS += src_scripttools
+contains(QT_CONFIG, declarative): SRC_SUBDIRS += src_declarative
SRC_SUBDIRS += src_plugins
src_winmain.subdir = $$QT_SOURCE_TREE/src/winmain
@@ -79,6 +80,8 @@ src_javascriptcore.subdir = $$QT_SOURCE_TREE/src/3rdparty/webkit/JavaScriptCore
src_javascriptcore.target = sub-javascriptcore
src_webkit.subdir = $$QT_SOURCE_TREE/src/3rdparty/webkit/WebCore
src_webkit.target = sub-webkit
+src_declarative.subdir = $$QT_SOURCE_TREE/src/declarative
+src_declarative.target = sub-declarative
#CONFIG += ordered
!wince*:!ordered {
@@ -103,6 +106,7 @@ src_webkit.target = sub-webkit
src_tools_uic3.depends = src_qt3support src_xml
src_tools_idc.depends = src_corelib
src_tools_activeqt.depends = src_tools_idc src_gui
+ src_declarative.depends = src_xml src_gui src_script src_network src_svg
src_plugins.depends = src_gui src_sql src_svg
contains(QT_CONFIG, webkit) {
src_webkit.depends = src_gui src_sql src_network src_xml
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index ae8a76e..7d617a3 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -66,7 +66,8 @@ enum PropertyFlags {
ResolveEditable = 0x00080000,
User = 0x00100000,
ResolveUser = 0x00200000,
- Notify = 0x00400000
+ Notify = 0x00400000,
+ Dynamic = 0x00800000
};
enum MethodFlags {
AccessPrivate = 0x00,
@@ -194,10 +195,10 @@ void Generator::generateCode()
QByteArray qualifiedClassNameIdentifier = cdef->qualified;
qualifiedClassNameIdentifier.replace(':', '_');
- int index = 12;
+ int index = 13;
fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData());
fprintf(out, "\n // content:\n");
- fprintf(out, " %4d, // revision\n", 2);
+ fprintf(out, " %4d, // revision\n", 3);
fprintf(out, " %4d, // classname\n", strreg(cdef->qualified));
fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0);
index += cdef->classInfoList.count() * 2;
@@ -217,6 +218,9 @@ void Generator::generateCode()
fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0,
isConstructible ? index : 0);
+ fprintf(out, " %4d, // flags\n", 0);
+
+
//
// Build classinfo array
//
@@ -371,7 +375,7 @@ void Generator::generateCode()
if (isQt || !cdef->hasQObject)
return;
- fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return &staticMetaObject;\n}\n",
+ fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;\n}\n",
cdef->qualified.constData());
//
// Generate smart cast function
@@ -394,8 +398,8 @@ void Generator::generateCode()
fprintf(out, " if (!strcmp(_clname, %s))\n return ", iface.at(j).interfaceId.constData());
for (int k = j; k >= 0; --k)
fprintf(out, "static_cast< %s*>(", iface.at(k).className.constData());
- fprintf(out, "const_cast< %s*>(this)%s;\n",
- cdef->classname.constData(), QByteArray(j+1, ')').constData());
+ fprintf(out, "%sconst_cast< %s*>(this)%s;\n",
+ (iface.at(j).isCast?"*":""), cdef->classname.constData(), QByteArray(j+1, ')').constData());
}
}
if (!purestSuperClass.isEmpty() && !isQObject) {
diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp
index 2a4fbf9..62c16ee 100644
--- a/src/tools/moc/keywords.cpp
+++ b/src/tools/moc/keywords.cpp
@@ -43,12 +43,12 @@
// DO NOT EDIT.
static const short keyword_trans[][128] = {
- {0,0,0,0,0,0,0,0,0,525,522,0,0,0,0,0,
+ {0,0,0,0,0,0,0,0,0,539,536,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 525,252,523,526,0,38,239,524,25,26,236,234,30,235,27,237,
+ 539,252,537,540,0,38,239,538,25,26,236,234,30,235,27,237,
22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43,
0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,21,8,8,8,8,8,8,8,8,8,31,527,32,238,8,
+ 8,21,8,8,8,8,8,8,8,8,8,31,541,32,238,8,
0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13,
14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -129,7 +129,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,290,222,0,0,461,0,0,0,
+ 0,0,0,0,0,0,0,0,290,222,0,0,475,0,0,0,
0,0,0,0,55,0,0,330,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -168,7 +168,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,485,0,0,0,0,0,0,0,0,0,0,357,
+ 0,0,0,0,499,0,0,0,0,0,0,0,0,0,0,357,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -190,7 +190,7 @@ static const short keyword_trans[][128] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0,
- 530,530,530,530,530,530,530,530,530,530,0,0,0,0,0,0,
+ 544,544,544,544,544,544,544,544,544,544,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -349,7 +349,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,529,0,0,0,0,528,
+ 0,0,0,0,0,0,0,0,0,0,543,0,0,0,0,542,
0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -385,7 +385,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,458,0,0,0,300,0,0,0,0,0,0,0,0,0,0,
+ 0,472,0,0,0,300,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -399,7 +399,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,475,0,0,0,0,0,372,
+ 0,0,0,0,0,0,0,0,0,489,0,0,0,0,0,372,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@@ -415,7 +415,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,513,0,437,0,0,0,465,0,0,471,0,0,0,
+ 0,0,0,527,0,437,0,0,0,479,0,0,485,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@@ -423,16 +423,24 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,458,0,0,0,0,0,0,0,0,0,0,440,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,450,0,506,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,497,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,486,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,450,0,520,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,511,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,500,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
@@ -884,7 +892,7 @@ static const struct
{CHARACTER, 46, 0, 0, CHARACTER},
{CHARACTER, 0, 84, 438, CHARACTER},
{CHARACTER, 0, 83, 387, CHARACTER},
- {CHARACTER, 0, 76, 440, CHARACTER},
+ {CHARACTER, 47, 0, 0, CHARACTER},
{CHARACTER, 0, 65, 441, CHARACTER},
{CHARACTER, 0, 83, 442, CHARACTER},
{CHARACTER, 0, 83, 443, CHARACTER},
@@ -894,7 +902,7 @@ static const struct
{CHARACTER, 0, 79, 447, CHARACTER},
{Q_CLASSINFO_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 78, 449, CHARACTER},
- {CHARACTER, 47, 0, 0, CHARACTER},
+ {CHARACTER, 48, 0, 0, CHARACTER},
{CHARACTER, 0, 69, 451, CHARACTER},
{CHARACTER, 0, 82, 452, CHARACTER},
{CHARACTER, 0, 70, 453, CHARACTER},
@@ -903,69 +911,83 @@ static const struct
{CHARACTER, 0, 69, 456, CHARACTER},
{CHARACTER, 0, 83, 457, CHARACTER},
{Q_INTERFACES_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 108, 459, CHARACTER},
- {CHARACTER, 0, 115, 460, CHARACTER},
+ {CHARACTER, 0, 83, 459, CHARACTER},
+ {CHARACTER, 0, 84, 460, CHARACTER},
+ {CHARACTER, 0, 95, 461, CHARACTER},
+ {CHARACTER, 0, 73, 462, CHARACTER},
+ {CHARACTER, 0, 78, 463, CHARACTER},
+ {CHARACTER, 0, 84, 464, CHARACTER},
+ {CHARACTER, 0, 69, 465, CHARACTER},
+ {CHARACTER, 0, 82, 466, CHARACTER},
+ {CHARACTER, 0, 70, 467, CHARACTER},
+ {CHARACTER, 0, 65, 468, CHARACTER},
+ {CHARACTER, 0, 67, 469, CHARACTER},
+ {CHARACTER, 0, 69, 470, CHARACTER},
+ {CHARACTER, 0, 83, 471, CHARACTER},
+ {Q_CAST_INTERFACES_TOKEN, 0, 0, 0, CHARACTER},
+ {CHARACTER, 0, 108, 473, CHARACTER},
+ {CHARACTER, 0, 115, 474, CHARACTER},
{SIGNALS, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 111, 462, CHARACTER},
- {CHARACTER, 0, 116, 463, CHARACTER},
- {CHARACTER, 0, 115, 464, CHARACTER},
+ {CHARACTER, 0, 111, 476, CHARACTER},
+ {CHARACTER, 0, 116, 477, CHARACTER},
+ {CHARACTER, 0, 115, 478, CHARACTER},
{SLOTS, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 71, 466, CHARACTER},
- {CHARACTER, 0, 78, 467, CHARACTER},
- {CHARACTER, 0, 65, 468, CHARACTER},
- {CHARACTER, 0, 76, 469, CHARACTER},
- {Q_SIGNAL_TOKEN, 0, 83, 470, CHARACTER},
+ {CHARACTER, 0, 71, 480, CHARACTER},
+ {CHARACTER, 0, 78, 481, CHARACTER},
+ {CHARACTER, 0, 65, 482, CHARACTER},
+ {CHARACTER, 0, 76, 483, CHARACTER},
+ {Q_SIGNAL_TOKEN, 0, 83, 484, CHARACTER},
{Q_SIGNALS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 79, 472, CHARACTER},
- {CHARACTER, 0, 84, 473, CHARACTER},
- {Q_SLOT_TOKEN, 0, 83, 474, CHARACTER},
+ {CHARACTER, 0, 79, 486, CHARACTER},
+ {CHARACTER, 0, 84, 487, CHARACTER},
+ {Q_SLOT_TOKEN, 0, 83, 488, CHARACTER},
{Q_SLOTS_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 86, 476, CHARACTER},
- {CHARACTER, 0, 65, 477, CHARACTER},
- {CHARACTER, 0, 84, 478, CHARACTER},
- {CHARACTER, 0, 69, 479, CHARACTER},
- {CHARACTER, 0, 95, 480, CHARACTER},
- {CHARACTER, 0, 83, 481, CHARACTER},
- {CHARACTER, 0, 76, 482, CHARACTER},
- {CHARACTER, 0, 79, 483, CHARACTER},
- {CHARACTER, 0, 84, 484, CHARACTER},
+ {CHARACTER, 0, 86, 490, CHARACTER},
+ {CHARACTER, 0, 65, 491, CHARACTER},
+ {CHARACTER, 0, 84, 492, CHARACTER},
+ {CHARACTER, 0, 69, 493, CHARACTER},
+ {CHARACTER, 0, 95, 494, CHARACTER},
+ {CHARACTER, 0, 83, 495, CHARACTER},
+ {CHARACTER, 0, 76, 496, CHARACTER},
+ {CHARACTER, 0, 79, 497, CHARACTER},
+ {CHARACTER, 0, 84, 498, CHARACTER},
{Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 48, 0, 0, CHARACTER},
- {CHARACTER, 0, 77, 487, CHARACTER},
- {CHARACTER, 0, 79, 488, CHARACTER},
- {CHARACTER, 0, 67, 489, CHARACTER},
- {CHARACTER, 0, 95, 490, CHARACTER},
- {CHARACTER, 0, 67, 491, CHARACTER},
- {CHARACTER, 0, 79, 492, CHARACTER},
- {CHARACTER, 0, 77, 493, CHARACTER},
- {CHARACTER, 0, 80, 494, CHARACTER},
- {CHARACTER, 0, 65, 495, CHARACTER},
- {CHARACTER, 0, 84, 496, CHARACTER},
+ {CHARACTER, 49, 0, 0, CHARACTER},
+ {CHARACTER, 0, 77, 501, CHARACTER},
+ {CHARACTER, 0, 79, 502, CHARACTER},
+ {CHARACTER, 0, 67, 503, CHARACTER},
+ {CHARACTER, 0, 95, 504, CHARACTER},
+ {CHARACTER, 0, 67, 505, CHARACTER},
+ {CHARACTER, 0, 79, 506, CHARACTER},
+ {CHARACTER, 0, 77, 507, CHARACTER},
+ {CHARACTER, 0, 80, 508, CHARACTER},
+ {CHARACTER, 0, 65, 509, CHARACTER},
+ {CHARACTER, 0, 84, 510, CHARACTER},
{Q_MOC_COMPAT_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 95, 498, CHARACTER},
- {CHARACTER, 0, 83, 499, CHARACTER},
- {CHARACTER, 0, 85, 500, CHARACTER},
- {CHARACTER, 0, 80, 501, CHARACTER},
- {CHARACTER, 0, 80, 502, CHARACTER},
- {CHARACTER, 0, 79, 503, CHARACTER},
- {CHARACTER, 0, 82, 504, CHARACTER},
- {CHARACTER, 0, 84, 505, CHARACTER},
+ {CHARACTER, 0, 95, 512, CHARACTER},
+ {CHARACTER, 0, 83, 513, CHARACTER},
+ {CHARACTER, 0, 85, 514, CHARACTER},
+ {CHARACTER, 0, 80, 515, CHARACTER},
+ {CHARACTER, 0, 80, 516, CHARACTER},
+ {CHARACTER, 0, 79, 517, CHARACTER},
+ {CHARACTER, 0, 82, 518, CHARACTER},
+ {CHARACTER, 0, 84, 519, CHARACTER},
{Q_QT3_SUPPORT_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 79, 507, CHARACTER},
- {CHARACTER, 0, 75, 508, CHARACTER},
- {CHARACTER, 0, 65, 509, CHARACTER},
- {CHARACTER, 0, 66, 510, CHARACTER},
- {CHARACTER, 0, 76, 511, CHARACTER},
- {CHARACTER, 0, 69, 512, CHARACTER},
+ {CHARACTER, 0, 79, 521, CHARACTER},
+ {CHARACTER, 0, 75, 522, CHARACTER},
+ {CHARACTER, 0, 65, 523, CHARACTER},
+ {CHARACTER, 0, 66, 524, CHARACTER},
+ {CHARACTER, 0, 76, 525, CHARACTER},
+ {CHARACTER, 0, 69, 526, CHARACTER},
{Q_INVOKABLE_TOKEN, 0, 0, 0, CHARACTER},
- {CHARACTER, 0, 82, 514, CHARACTER},
- {CHARACTER, 0, 73, 515, CHARACTER},
- {CHARACTER, 0, 80, 516, CHARACTER},
- {CHARACTER, 0, 84, 517, CHARACTER},
- {CHARACTER, 0, 65, 518, CHARACTER},
- {CHARACTER, 0, 66, 519, CHARACTER},
- {CHARACTER, 0, 76, 520, CHARACTER},
- {CHARACTER, 0, 69, 521, CHARACTER},
+ {CHARACTER, 0, 82, 528, CHARACTER},
+ {CHARACTER, 0, 73, 529, CHARACTER},
+ {CHARACTER, 0, 80, 530, CHARACTER},
+ {CHARACTER, 0, 84, 531, CHARACTER},
+ {CHARACTER, 0, 65, 532, CHARACTER},
+ {CHARACTER, 0, 66, 533, CHARACTER},
+ {CHARACTER, 0, 76, 534, CHARACTER},
+ {CHARACTER, 0, 69, 535, CHARACTER},
{Q_SCRIPTABLE_TOKEN, 0, 0, 0, CHARACTER},
{NEWLINE, 0, 0, 0, NOTOKEN},
{QUOTE, 0, 0, 0, NOTOKEN},
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index a6a0ba1..74ca1ad 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -654,8 +654,11 @@ void Moc::parse()
case Q_CLASSINFO_TOKEN:
parseClassInfo(&def);
break;
+ case Q_CAST_INTERFACES_TOKEN:
+ parseInterfaces(&def, true);
+ break;
case Q_INTERFACES_TOKEN:
- parseInterfaces(&def);
+ parseInterfaces(&def, false);
break;
case Q_PRIVATE_SLOT_TOKEN:
parseSlotInPrivate(&def, access);
@@ -1025,12 +1028,12 @@ void Moc::parseClassInfo(ClassDef *def)
def->classInfoList += infoDef;
}
-void Moc::parseInterfaces(ClassDef *def)
+void Moc::parseInterfaces(ClassDef *def, bool isCast)
{
next(LPAREN);
while (test(IDENTIFIER)) {
QList<ClassDef::Interface> iface;
- iface += ClassDef::Interface(lexem());
+ iface += ClassDef::Interface(lexem(), isCast);
while (test(SCOPE)) {
iface.last().className += lexem();
next(IDENTIFIER);
@@ -1038,7 +1041,7 @@ void Moc::parseInterfaces(ClassDef *def)
}
while (test(COLON)) {
next(IDENTIFIER);
- iface += ClassDef::Interface(lexem());
+ iface += ClassDef::Interface(lexem(), isCast);
while (test(SCOPE)) {
iface.last().className += lexem();
next(IDENTIFIER);
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index 689104c..c02864a 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -144,10 +144,11 @@ struct ClassDef {
struct Interface
{
- inline explicit Interface(const QByteArray &_className)
- : className(_className) {}
+ inline explicit Interface(const QByteArray &_className, bool _isCast)
+ : className(_className), isCast(_isCast) {}
QByteArray className;
QByteArray interfaceId;
+ bool isCast;
};
QList<QList<Interface> >interfaceList;
@@ -217,7 +218,7 @@ public:
void parseEnumOrFlag(ClassDef *def, bool isFlag);
void parseFlag(ClassDef *def);
void parseClassInfo(ClassDef *def);
- void parseInterfaces(ClassDef *def);
+ void parseInterfaces(ClassDef *def, bool isCast);
void parseDeclareInterface();
void parseDeclareMetatype();
void parseSlotInPrivate(ClassDef *def, FunctionDef::Access access);
diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h
index 13c9a1d..7734a63 100644
--- a/src/tools/moc/token.h
+++ b/src/tools/moc/token.h
@@ -176,6 +176,7 @@ enum Token {
Q_DECLARE_METATYPE_TOKEN,
Q_CLASSINFO_TOKEN,
Q_INTERFACES_TOKEN,
+ Q_CAST_INTERFACES_TOKEN,
Q_SIGNALS_TOKEN,
Q_SLOTS_TOKEN,
Q_SIGNAL_TOKEN,
diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp
index 116be2b..a1a8215 100644
--- a/src/tools/moc/util/generate_keywords.cpp
+++ b/src/tools/moc/util/generate_keywords.cpp
@@ -237,6 +237,7 @@ static const Keyword keywords[] = {
{ "Q_SETS", "Q_FLAGS_TOKEN" },
{ "Q_CLASSINFO", "Q_CLASSINFO_TOKEN" },
{ "Q_INTERFACES", "Q_INTERFACES_TOKEN" },
+ { "Q_CAST_INTERFACES", "Q_CAST_INTERFACES_TOKEN" },
{ "signals", "SIGNALS" },
{ "slots", "SLOTS" },
{ "Q_SIGNALS", "Q_SIGNALS_TOKEN" },
diff --git a/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp b/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp
index 4a5c219..9bd4425 100644
--- a/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp
+++ b/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp
@@ -111,7 +111,7 @@ QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri,
networkLoop.connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(error(QNetworkReply::NetworkError)));
networkLoop.connect(reply, SIGNAL(finished()), SLOT(finished()));
- if(networkLoop.exec())
+ if(networkLoop.exec(QEventLoop::ExcludeUserInputEvents))
{
const QString errorMessage(escape(reply->errorString()));